aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
Diffstat (limited to 'src/server')
-rw-r--r--src/server/authserver/Server/AuthSession.cpp4
-rw-r--r--src/server/database/Database/Implementation/WorldDatabase.cpp1
-rw-r--r--src/server/database/Database/Implementation/WorldDatabase.h1
-rw-r--r--src/server/game/AI/CoreAI/PassiveAI.cpp4
-rw-r--r--src/server/game/AI/CoreAI/TotemAI.cpp2
-rw-r--r--src/server/game/AI/CoreAI/UnitAI.cpp2
-rw-r--r--src/server/game/AI/CoreAI/UnitAI.h5
-rw-r--r--src/server/game/AI/CreatureAI.h7
-rw-r--r--src/server/game/AI/PlayerAI/PlayerAI.cpp37
-rw-r--r--src/server/game/AI/PlayerAI/PlayerAI.h4
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.cpp10
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.h4
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp544
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedEscortAI.h135
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp2
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedFollowerAI.h4
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp647
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.h81
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp158
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp65
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h64
-rw-r--r--src/server/game/Accounts/RBAC.h16
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp4
-rw-r--r--src/server/game/Battlefield/Battlefield.cpp7
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp2
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.cpp3
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp6
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAB.h10
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp1
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAV.h20
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp6
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp3
-rw-r--r--src/server/game/Calendar/CalendarMgr.cpp6
-rw-r--r--src/server/game/Chat/Chat.cpp153
-rw-r--r--src/server/game/Chat/Chat.h25
-rw-r--r--src/server/game/Chat/ChatLink.cpp2
-rw-r--r--src/server/game/Combat/ThreatManager.h6
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp6
-rw-r--r--src/server/game/Conditions/ConditionMgr.h2
-rw-r--r--src/server/game/DataStores/DBCEnums.h2
-rw-r--r--src/server/game/DataStores/DBCStores.cpp10
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp4
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp469
-rw-r--r--src/server/game/Entities/Creature/Creature.h47
-rw-r--r--src/server/game/Entities/Creature/CreatureData.h39
-rw-r--r--src/server/game/Entities/Creature/CreatureGroups.cpp18
-rw-r--r--src/server/game/Entities/Creature/CreatureGroups.h2
-rw-r--r--src/server/game/Entities/Creature/GossipDef.cpp42
-rw-r--r--src/server/game/Entities/Creature/TemporarySummon.cpp22
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp262
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h14
-rw-r--r--src/server/game/Entities/GameObject/GameObjectData.h25
-rw-r--r--src/server/game/Entities/Item/ItemEnchantmentMgr.cpp2
-rw-r--r--src/server/game/Entities/Object/Object.cpp4
-rw-r--r--src/server/game/Entities/Object/Object.h4
-rw-r--r--src/server/game/Entities/Object/ObjectGuid.cpp8
-rw-r--r--src/server/game/Entities/Object/ObjectGuid.h5
-rw-r--r--src/server/game/Entities/Object/Position.h25
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp24
-rw-r--r--src/server/game/Entities/Player/Player.cpp135
-rw-r--r--src/server/game/Entities/Player/Player.h4
-rw-r--r--src/server/game/Entities/Player/PlayerTaxi.cpp14
-rw-r--r--src/server/game/Entities/Player/PlayerTaxi.h6
-rw-r--r--src/server/game/Entities/Transport/Transport.cpp20
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp45
-rw-r--r--src/server/game/Entities/Unit/Unit.h4
-rw-r--r--src/server/game/Entities/Unit/UnitDefines.h2
-rwxr-xr-xsrc/server/game/Entities/Vehicle/Vehicle.cpp12
-rw-r--r--src/server/game/Events/GameEventMgr.cpp170
-rw-r--r--src/server/game/Events/GameEventMgr.h6
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp572
-rw-r--r--src/server/game/Globals/ObjectMgr.h102
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.h42
-rw-r--r--src/server/game/Grids/ObjectGridLoader.cpp56
-rw-r--r--src/server/game/Groups/Group.cpp3
-rw-r--r--src/server/game/Handlers/BattleGroundHandler.cpp3
-rw-r--r--src/server/game/Handlers/CalendarHandler.cpp9
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp8
-rw-r--r--src/server/game/Handlers/ChatHandler.cpp14
-rw-r--r--src/server/game/Handlers/ItemHandler.cpp4
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp1
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp7
-rw-r--r--src/server/game/Handlers/NPCHandler.cpp9
-rw-r--r--src/server/game/Handlers/PetitionsHandler.cpp12
-rw-r--r--src/server/game/Handlers/QuestHandler.cpp4
-rw-r--r--src/server/game/Handlers/TaxiHandler.cpp23
-rw-r--r--src/server/game/Instances/InstanceScript.cpp96
-rw-r--r--src/server/game/Instances/InstanceScript.h17
-rw-r--r--src/server/game/Loot/LootMgr.cpp22
-rw-r--r--src/server/game/Maps/Map.cpp645
-rw-r--r--src/server/game/Maps/Map.h168
-rw-r--r--src/server/game/Maps/MapManager.h8
-rw-r--r--src/server/game/Maps/MapScripts.cpp2
-rw-r--r--src/server/game/Maps/SpawnData.h76
-rw-r--r--src/server/game/Miscellaneous/Formulas.h7
-rw-r--r--src/server/game/Miscellaneous/Language.h27
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h2
-rw-r--r--src/server/game/Movement/MotionMaster.cpp150
-rw-r--r--src/server/game/Movement/MotionMaster.h17
-rwxr-xr-xsrc/server/game/Movement/MovementGenerator.h3
-rw-r--r--src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp6
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp7
-rw-r--r--src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp4
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp309
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h97
-rw-r--r--src/server/game/Movement/Waypoints/WaypointDefines.h71
-rw-r--r--src/server/game/Movement/Waypoints/WaypointManager.cpp101
-rw-r--r--src/server/game/Movement/Waypoints/WaypointManager.h38
-rw-r--r--src/server/game/OutdoorPvP/OutdoorPvP.cpp10
-rw-r--r--src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp2
-rw-r--r--src/server/game/Pools/PoolMgr.cpp147
-rw-r--r--src/server/game/Pools/PoolMgr.h3
-rw-r--r--src/server/game/Quests/QuestDef.cpp27
-rw-r--r--src/server/game/Quests/QuestDef.h3
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp53
-rw-r--r--src/server/game/Scripting/ScriptMgr.h70
-rw-r--r--src/server/game/Scripting/ScriptSystem.cpp56
-rw-r--r--src/server/game/Scripting/ScriptSystem.h46
-rw-r--r--src/server/game/Server/WorldSession.cpp2
-rw-r--r--src/server/game/Skills/SkillDiscovery.cpp2
-rw-r--r--src/server/game/Skills/SkillExtraItems.cpp11
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp6
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp3
-rw-r--r--src/server/game/Spells/Spell.cpp15
-rw-r--r--src/server/game/Spells/SpellEffects.cpp40
-rw-r--r--src/server/game/Spells/SpellInfo.cpp22
-rw-r--r--src/server/game/Spells/SpellMgr.cpp22
-rw-r--r--src/server/game/Spells/SpellScript.h4
-rw-r--r--src/server/game/Tools/PlayerDump.cpp2
-rw-r--r--src/server/game/Warden/WardenCheckMgr.cpp8
-rw-r--r--src/server/game/Weather/WeatherMgr.cpp2
-rw-r--r--src/server/game/World/World.cpp164
-rw-r--r--src/server/game/World/World.h27
-rw-r--r--src/server/scripts/CMakeLists.txt2
-rw-r--r--src/server/scripts/Commands/cs_ban.cpp3
-rw-r--r--src/server/scripts/Commands/cs_debug.cpp2
-rw-r--r--src/server/scripts/Commands/cs_disable.cpp6
-rw-r--r--src/server/scripts/Commands/cs_go.cpp28
-rw-r--r--src/server/scripts/Commands/cs_gobject.cpp70
-rw-r--r--src/server/scripts/Commands/cs_instance.cpp6
-rw-r--r--src/server/scripts/Commands/cs_list.cpp177
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp31
-rw-r--r--src/server/scripts/Commands/cs_npc.cpp246
-rw-r--r--src/server/scripts/Commands/cs_reload.cpp20
-rw-r--r--src/server/scripts/Commands/cs_wp.cpp20
-rw-r--r--src/server/scripts/EasternKingdoms/AlteracValley/alterac_valley.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/AlteracValley/boss_drekthar.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp16
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.h2
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_coren_direbrew.cpp744
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp6
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp3
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp8
-rw-r--r--src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp16
-rw-r--r--src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp46
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp16
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp10
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp10
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_herod.cpp7
-rw-r--r--src/server/scripts/EasternKingdoms/Scholomance/boss_illucia_barov.cpp9
-rw-r--r--src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp8
-rw-r--r--src/server/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp42
-rw-r--r--src/server/scripts/EasternKingdoms/Stratholme/stratholme.h15
-rw-r--r--src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp1249
-rw-r--r--src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp10
-rw-r--r--src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp7
-rw-r--r--src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h5
-rw-r--r--src/server/scripts/EasternKingdoms/ZulAman/zulaman.h2
-rw-r--r--src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp6
-rw-r--r--src/server/scripts/EasternKingdoms/zone_arathi_highlands.cpp10
-rw-r--r--src/server/scripts/EasternKingdoms/zone_burning_steppes.cpp94
-rw-r--r--src/server/scripts/EasternKingdoms/zone_ghostlands.cpp6
-rw-r--r--src/server/scripts/EasternKingdoms/zone_hinterlands.cpp22
-rw-r--r--src/server/scripts/EasternKingdoms/zone_isle_of_queldanas.cpp94
-rw-r--r--src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp10
-rw-r--r--src/server/scripts/EasternKingdoms/zone_silverpine_forest.cpp6
-rw-r--r--src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp16
-rw-r--r--src/server/scripts/EasternKingdoms/zone_stranglethorn_vale.cpp136
-rw-r--r--src/server/scripts/EasternKingdoms/zone_swamp_of_sorrows.cpp12
-rw-r--r--src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp95
-rw-r--r--src/server/scripts/EasternKingdoms/zone_undercity.cpp6
-rw-r--r--src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp97
-rw-r--r--src/server/scripts/EasternKingdoms/zone_wetlands.cpp6
-rw-r--r--src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp6
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp6
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp10
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp6
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp6
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp8
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h4
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp38
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.h2
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp18
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp18
-rw-r--r--src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp6
-rw-r--r--src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp4
-rw-r--r--src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp5
-rw-r--r--src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp4
-rw-r--r--src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.cpp14
-rw-r--r--src/server/scripts/Kalimdor/zone_ashenvale.cpp20
-rw-r--r--src/server/scripts/Kalimdor/zone_azshara.cpp99
-rw-r--r--src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp134
-rw-r--r--src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp8
-rw-r--r--src/server/scripts/Kalimdor/zone_darkshore.cpp6
-rw-r--r--src/server/scripts/Kalimdor/zone_desolace.cpp8
-rw-r--r--src/server/scripts/Kalimdor/zone_feralas.cpp6
-rw-r--r--src/server/scripts/Kalimdor/zone_moonglade.cpp12
-rw-r--r--src/server/scripts/Kalimdor/zone_orgrimmar.cpp10
-rw-r--r--src/server/scripts/Kalimdor/zone_silithus.cpp4
-rw-r--r--src/server/scripts/Kalimdor/zone_stonetalon_mountains.cpp6
-rw-r--r--src/server/scripts/Kalimdor/zone_tanaris.cpp137
-rw-r--r--src/server/scripts/Kalimdor/zone_the_barrens.cpp14
-rw-r--r--src/server/scripts/Kalimdor/zone_thousand_needles.cpp18
-rw-r--r--src/server/scripts/Kalimdor/zone_thunder_bluff.cpp10
-rw-r--r--src/server/scripts/Kalimdor/zone_ungoro_crater.cpp8
-rw-r--r--src/server/scripts/Kalimdor/zone_winterspring.cpp55
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/Ahnkahet/ahnkahet.h14
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp368
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp837
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp16
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp186
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/AzjolNerub/azjol_nerub.h3
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp22
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp17
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp34
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp7
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp6
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.cpp6
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp8
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp8
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp10
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp2
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp16
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp54
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp10
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp47
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp42
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp300
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp90
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h235
-rw-r--r--src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp4
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp2
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp4
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp4
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp62
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp8
-rw-r--r--src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp15
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp8
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp75
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp22
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp29
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp75
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp4
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp10
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h4
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp24
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp11
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp11
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp7
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp6
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp20
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp2
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp552
-rw-r--r--src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp21
-rw-r--r--src/server/scripts/Northrend/Naxxramas/naxxramas.h4
-rw-r--r--src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp4
-rw-r--r--src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp6
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp12
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp987
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp11
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp6
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp2416
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp10
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp8
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp4
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h16
-rw-r--r--src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp4
-rw-r--r--src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp8
-rw-r--r--src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp325
-rw-r--r--src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp43
-rw-r--r--src/server/scripts/Northrend/VaultOfArchavon/vault_of_archavon.h8
-rw-r--r--src/server/scripts/Northrend/VioletHold/violet_hold.cpp10
-rw-r--r--src/server/scripts/Northrend/zone_borean_tundra.cpp140
-rw-r--r--src/server/scripts/Northrend/zone_dalaran.cpp90
-rw-r--r--src/server/scripts/Northrend/zone_dragonblight.cpp2
-rw-r--r--src/server/scripts/Northrend/zone_grizzly_hills.cpp14
-rw-r--r--src/server/scripts/Northrend/zone_howling_fjord.cpp16
-rw-r--r--src/server/scripts/Northrend/zone_icecrown.cpp2
-rw-r--r--src/server/scripts/Northrend/zone_sholazar_basin.cpp297
-rw-r--r--src/server/scripts/Northrend/zone_storm_peaks.cpp27
-rw-r--r--src/server/scripts/Northrend/zone_zuldrak.cpp2
-rw-r--r--src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_talon_king_ikiss.cpp3
-rw-r--r--src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp10
-rw-r--r--src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp241
-rw-r--r--src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp2
-rw-r--r--src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp40
-rw-r--r--src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.h9
-rw-r--r--src/server/scripts/Outland/BlackTemple/black_temple.cpp370
-rw-r--r--src/server/scripts/Outland/BlackTemple/black_temple.h12
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp477
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_illidan.cpp3229
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_illidari_council.cpp1110
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp412
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp1053
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp1563
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_supremus.cpp269
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp580
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp323
-rw-r--r--src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp38
-rw-r--r--src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp20
-rw-r--r--src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp2
-rw-r--r--src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp2
-rw-r--r--src/server/scripts/Outland/GruulsLair/boss_gruul.cpp2
-rw-r--r--src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp8
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/boss_magtheridon.cpp4
-rw-r--r--src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp4
-rw-r--r--src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp3
-rw-r--r--src/server/scripts/Outland/boss_doomlord_kazzak.cpp2
-rw-r--r--src/server/scripts/Outland/zone_hellfire_peninsula.cpp16
-rw-r--r--src/server/scripts/Outland/zone_nagrand.cpp16
-rw-r--r--src/server/scripts/Outland/zone_netherstorm.cpp77
-rw-r--r--src/server/scripts/Outland/zone_shadowmoon_valley.cpp113
-rw-r--r--src/server/scripts/Outland/zone_shattrath_city.cpp337
-rw-r--r--src/server/scripts/Outland/zone_terokkar_forest.cpp354
-rw-r--r--src/server/scripts/Outland/zone_zangarmarsh.cpp165
-rw-r--r--src/server/scripts/Pet/pet_hunter.cpp4
-rw-r--r--src/server/scripts/Spells/spell_dk.cpp2
-rw-r--r--src/server/scripts/Spells/spell_druid.cpp8
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp4519
-rw-r--r--src/server/scripts/Spells/spell_holiday.cpp235
-rw-r--r--src/server/scripts/Spells/spell_hunter.cpp8
-rw-r--r--src/server/scripts/Spells/spell_item.cpp4997
-rw-r--r--src/server/scripts/Spells/spell_mage.cpp30
-rw-r--r--src/server/scripts/Spells/spell_paladin.cpp6
-rw-r--r--src/server/scripts/Spells/spell_priest.cpp6
-rw-r--r--src/server/scripts/Spells/spell_quest.cpp2
-rw-r--r--src/server/scripts/Spells/spell_rogue.cpp4
-rw-r--r--src/server/scripts/Spells/spell_shaman.cpp8
-rw-r--r--src/server/scripts/Spells/spell_warlock.cpp6
-rw-r--r--src/server/scripts/Spells/spell_warrior.cpp6
-rw-r--r--src/server/scripts/World/action_ip_logger.cpp10
-rw-r--r--src/server/scripts/World/areatrigger_scripts.cpp33
-rw-r--r--src/server/scripts/World/boss_emerald_dragons.cpp4
-rw-r--r--src/server/scripts/World/go_scripts.cpp189
-rw-r--r--src/server/scripts/World/item_scripts.cpp28
-rw-r--r--src/server/scripts/World/npc_innkeeper.cpp21
-rw-r--r--src/server/scripts/World/npc_professions.cpp221
-rw-r--r--src/server/scripts/World/npcs_special.cpp54
-rw-r--r--src/server/shared/DataStores/DBCStore.cpp2
-rw-r--r--src/server/shared/Packets/ByteBuffer.cpp2
-rw-r--r--src/server/worldserver/worldserver.conf.dist161
357 files changed, 19613 insertions, 20787 deletions
diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp
index 49602119de0..a5db0e37928 100644
--- a/src/server/authserver/Server/AuthSession.cpp
+++ b/src/server/authserver/Server/AuthSession.cpp
@@ -576,7 +576,7 @@ bool AuthSession::HandleLogonProof()
PreparedStatement *stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGONPROOF);
stmt->setString(0, K.AsHexStr());
- stmt->setString(1, GetRemoteIpAddress().to_string().c_str());
+ stmt->setString(1, GetRemoteIpAddress().to_string());
stmt->setUInt32(2, GetLocaleByName(_localizationName));
stmt->setString(3, _os);
stmt->setString(4, _accountInfo.Login);
@@ -885,6 +885,8 @@ void AuthSession::RealmListCallback(PreparedQueryResult result)
hdr.append(RealmListSizeBuffer); // append RealmList's size buffer
hdr.append(pkt); // append realms in the realmlist
SendPacket(hdr);
+
+ _status = STATUS_AUTHED;
}
// Make the SRP6 calculation from hash in dB
diff --git a/src/server/database/Database/Implementation/WorldDatabase.cpp b/src/server/database/Database/Implementation/WorldDatabase.cpp
index c64e7a9c2fc..654074d594b 100644
--- a/src/server/database/Database/Implementation/WorldDatabase.cpp
+++ b/src/server/database/Database/Implementation/WorldDatabase.cpp
@@ -92,6 +92,7 @@ void WorldDatabaseConnection::DoPrepareStatements()
PrepareStatement(WORLD_DEL_DISABLES, "DELETE FROM disables WHERE entry = ? AND sourceType = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_UPD_CREATURE_ZONE_AREA_DATA, "UPDATE creature SET zoneId = ?, areaId = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_UPD_GAMEOBJECT_ZONE_AREA_DATA, "UPDATE gameobject SET zoneId = ?, areaId = ? WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(WORLD_DEL_SPAWNGROUP_MEMBER, "DELETE FROM spawn_group WHERE spawnType = ? AND spawnId = ?", CONNECTION_ASYNC);
}
WorldDatabaseConnection::WorldDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo)
diff --git a/src/server/database/Database/Implementation/WorldDatabase.h b/src/server/database/Database/Implementation/WorldDatabase.h
index b68f53bb173..f7784ad256f 100644
--- a/src/server/database/Database/Implementation/WorldDatabase.h
+++ b/src/server/database/Database/Implementation/WorldDatabase.h
@@ -98,6 +98,7 @@ enum WorldDatabaseStatements : uint32
WORLD_DEL_DISABLES,
WORLD_UPD_CREATURE_ZONE_AREA_DATA,
WORLD_UPD_GAMEOBJECT_ZONE_AREA_DATA,
+ WORLD_DEL_SPAWNGROUP_MEMBER,
MAX_WORLDDATABASE_STATEMENTS
};
diff --git a/src/server/game/AI/CoreAI/PassiveAI.cpp b/src/server/game/AI/CoreAI/PassiveAI.cpp
index 2eca6c64c9e..abbff7a870b 100644
--- a/src/server/game/AI/CoreAI/PassiveAI.cpp
+++ b/src/server/game/AI/CoreAI/PassiveAI.cpp
@@ -29,7 +29,7 @@ int32 NullCreatureAI::Permissible(Creature const* creature)
return PERMIT_BASE_PROACTIVE + 50;
if (creature->IsTrigger())
- return PERMIT_BASE_REACTIVE;
+ return PERMIT_BASE_PROACTIVE;
return PERMIT_BASE_IDLE;
}
@@ -105,7 +105,7 @@ void TriggerAI::IsSummonedBy(Unit* summoner)
int32 TriggerAI::Permissible(Creature const* creature)
{
if (creature->IsTrigger() && creature->m_spells[0])
- return PERMIT_BASE_PROACTIVE;
+ return PERMIT_BASE_SPECIAL;
return PERMIT_BASE_NO;
}
diff --git a/src/server/game/AI/CoreAI/TotemAI.cpp b/src/server/game/AI/CoreAI/TotemAI.cpp
index da484e20983..365f0ca5ce8 100644
--- a/src/server/game/AI/CoreAI/TotemAI.cpp
+++ b/src/server/game/AI/CoreAI/TotemAI.cpp
@@ -72,7 +72,7 @@ void TotemAI::UpdateAI(uint32 /*diff*/)
me->IsFriendlyTo(victim) || !me->CanSeeOrDetect(victim))
{
victim = nullptr;
- Trinity::NearestAttackableUnitInObjectRangeCheck u_check(me, me, max_range);
+ Trinity::NearestAttackableUnitInObjectRangeCheck u_check(me, me->GetCharmerOrOwnerOrSelf(), max_range);
Trinity::UnitLastSearcher<Trinity::NearestAttackableUnitInObjectRangeCheck> checker(me, victim, u_check);
Cell::VisitAllObjects(me, checker, max_range);
}
diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp
index 92c9c8e3fb6..244b0b5e047 100644
--- a/src/server/game/AI/CoreAI/UnitAI.cpp
+++ b/src/server/game/AI/CoreAI/UnitAI.cpp
@@ -190,7 +190,7 @@ void UnitAI::DoCastAOE(uint32 spellId, bool triggered)
if (!triggered && me->HasUnitState(UNIT_STATE_CASTING))
return;
- me->CastSpell((Unit*)nullptr, spellId, triggered);
+ me->CastSpell(nullptr, spellId, triggered);
}
uint32 UnitAI::GetDialogStatus(Player* /*player*/)
diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h
index 30a0575c3d2..1078c16f8de 100644
--- a/src/server/game/AI/CoreAI/UnitAI.h
+++ b/src/server/game/AI/CoreAI/UnitAI.h
@@ -330,6 +330,11 @@ class TC_GAME_API UnitAI
// Called when the dialog status between a player and the creature is requested.
virtual uint32 GetDialogStatus(Player* /*player*/);
+ virtual void WaypointPathStarted(uint32 /*nodeId*/, uint32 /*pathId*/) { }
+ virtual void WaypointStarted(uint32 /*nodeId*/, uint32 /*pathId*/) { }
+ virtual void WaypointReached(uint32 /*nodeId*/, uint32 /*pathId*/) { }
+ virtual void WaypointPathEnded(uint32 /*nodeId*/, uint32 /*pathId*/) { }
+
private:
UnitAI(UnitAI const& right) = delete;
UnitAI& operator=(UnitAI const& right) = delete;
diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h
index bd7a6efab22..015e46cccdd 100644
--- a/src/server/game/AI/CreatureAI.h
+++ b/src/server/game/AI/CreatureAI.h
@@ -134,8 +134,8 @@ class TC_GAME_API CreatureAI : public UnitAI
virtual bool IsEscorted() const { return false; }
- // Called when creature is spawned or respawned
- virtual void JustRespawned() { }
+ // Called when creature appears in the world (spawn, respawn, grid load etc...)
+ virtual void JustAppeared() { }
// Called at waypoint reached or point movement finished
virtual void MovementInform(uint32 /*type*/, uint32 /*id*/) { }
@@ -187,6 +187,9 @@ class TC_GAME_API CreatureAI : public UnitAI
// If a PlayerAI* is returned, that AI is placed on the player instead of the default charm AI
// Object destruction is handled by Unit::RemoveCharmedBy
virtual PlayerAI* GetAIForCharmedPlayer(Player* /*who*/) { return nullptr; }
+ // Should return true if the NPC is target of an escort quest
+ // If onlyIfActive is set, should return true only if the escort quest is currently active
+ virtual bool IsEscortNPC(bool /*onlyIfActive*/) const { return false; }
// intended for encounter design/debugging. do not use for other purposes. expensive.
int32 VisualizeBoundary(uint32 duration, Unit* owner = nullptr, bool fill = false) const;
diff --git a/src/server/game/AI/PlayerAI/PlayerAI.cpp b/src/server/game/AI/PlayerAI/PlayerAI.cpp
index 92f1c6f06dc..a103b34ff56 100644
--- a/src/server/game/AI/PlayerAI/PlayerAI.cpp
+++ b/src/server/game/AI/PlayerAI/PlayerAI.cpp
@@ -769,18 +769,30 @@ Unit* PlayerAI::SelectAttackTarget() const
return me->GetCharmer() ? me->GetCharmer()->GetVictim() : nullptr;
}
-struct UncontrolledTargetSelectPredicate
+struct ValidTargetSelectPredicate
{
+ ValidTargetSelectPredicate(UnitAI const* ai) : _ai(ai) { }
+ UnitAI const* const _ai;
bool operator()(Unit const* target) const
{
- return !target->HasBreakableByDamageCrowdControlAura();
+ return _ai->CanAIAttack(target);
}
};
+bool SimpleCharmedPlayerAI::CanAIAttack(Unit const* who) const
+{
+ if (!me->IsValidAttackTarget(who) || who->HasBreakableByDamageCrowdControlAura())
+ return false;
+ if (Unit* charmer = me->GetCharmer())
+ if (!charmer->IsValidAttackTarget(who))
+ return false;
+ return UnitAI::CanAIAttack(who);
+}
+
Unit* SimpleCharmedPlayerAI::SelectAttackTarget() const
{
if (Unit* charmer = me->GetCharmer())
- return charmer->IsAIEnabled ? charmer->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0, UncontrolledTargetSelectPredicate()) : charmer->GetVictim();
+ return charmer->IsAIEnabled ? charmer->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0, ValidTargetSelectPredicate(this)) : charmer->GetVictim();
return nullptr;
}
@@ -1316,11 +1328,23 @@ void SimpleCharmedPlayerAI::UpdateAI(const uint32 diff)
if (charmer->IsEngaged())
{
Unit* target = me->GetVictim();
- if (!target || !charmer->IsValidAttackTarget(target) || target->HasBreakableByDamageCrowdControlAura())
+ if (!target || !CanAIAttack(target))
{
target = SelectAttackTarget();
- if (!target)
+ if (!target || !CanAIAttack(target))
+ {
+ if (!_isFollowing)
+ {
+ _isFollowing = true;
+ me->AttackStop();
+ me->CastStop();
+ me->StopMoving();
+ me->GetMotionMaster()->Clear();
+ me->GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
+ }
return;
+ }
+ _isFollowing = false;
if (IsRangedAttacker())
{
@@ -1373,8 +1397,9 @@ void SimpleCharmedPlayerAI::UpdateAI(const uint32 diff)
DoAutoAttackIfReady();
}
- else
+ else if (!_isFollowing)
{
+ _isFollowing = true;
me->AttackStop();
me->CastStop();
me->StopMoving();
diff --git a/src/server/game/AI/PlayerAI/PlayerAI.h b/src/server/game/AI/PlayerAI/PlayerAI.h
index 8afc5ab3ce9..faff09b6b6e 100644
--- a/src/server/game/AI/PlayerAI/PlayerAI.h
+++ b/src/server/game/AI/PlayerAI/PlayerAI.h
@@ -97,11 +97,12 @@ class TC_GAME_API PlayerAI : public UnitAI
class TC_GAME_API SimpleCharmedPlayerAI : public PlayerAI
{
public:
- SimpleCharmedPlayerAI(Player* player) : PlayerAI(player), _castCheckTimer(500), _chaseCloser(false), _forceFacing(true) { }
+ SimpleCharmedPlayerAI(Player* player) : PlayerAI(player), _castCheckTimer(2500), _chaseCloser(false), _forceFacing(true), _isFollowing(false) { }
void UpdateAI(uint32 diff) override;
void OnCharmed(bool apply) override;
protected:
+ bool CanAIAttack(Unit const* who) const override;
Unit* SelectAttackTarget() const override;
private:
@@ -109,6 +110,7 @@ class TC_GAME_API SimpleCharmedPlayerAI : public PlayerAI
uint32 _castCheckTimer;
bool _chaseCloser;
bool _forceFacing;
+ bool _isFollowing;
};
#endif
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
index e9e252bcf35..afa7e789b7a 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
@@ -478,7 +478,7 @@ void BossAI::_Reset()
events.Reset();
summons.DespawnAll();
scheduler.CancelAll();
- if (instance)
+ if (instance && instance->GetBossState(_bossId) != DONE)
instance->SetBossState(_bossId, NOT_STARTED);
}
@@ -564,12 +564,12 @@ bool BossAI::CanAIAttack(Unit const* target) const
return CheckBoundary(target);
}
-void BossAI::_DespawnAtEvade(uint32 delayToRespawn /*= 30*/, Creature* who /*= nullptr*/)
+void BossAI::_DespawnAtEvade(Seconds delayToRespawn, Creature* who)
{
- if (delayToRespawn < 2)
+ if (delayToRespawn < Seconds(2))
{
- TC_LOG_ERROR("scripts", "_DespawnAtEvade called with delay of %u seconds, defaulting to 2.", delayToRespawn);
- delayToRespawn = 2;
+ TC_LOG_ERROR("scripts", "_DespawnAtEvade called with delay of %ld seconds, defaulting to 2.", delayToRespawn.count());
+ delayToRespawn = Seconds(2);
}
if (!who)
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h
index 6fc85b6a81a..9f2e49c1ffb 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h
@@ -366,8 +366,8 @@ class TC_GAME_API BossAI : public ScriptedAI
void _EnterCombat();
void _JustDied();
void _JustReachedHome();
- void _DespawnAtEvade(uint32 delayToRespawn = 30, Creature* who = nullptr);
- void _DespawnAtEvade(Seconds const& time, Creature* who = nullptr) { _DespawnAtEvade(uint32(time.count()), who); }
+ void _DespawnAtEvade(Seconds delayToRespawn, Creature* who = nullptr);
+ void _DespawnAtEvade(uint32 delayToRespawn = 30, Creature* who = nullptr) { _DespawnAtEvade(Seconds(delayToRespawn), who); }
void TeleportCheaters();
diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
index bcf060e2ad6..376aceba4ba 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
@@ -16,21 +16,17 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Npc_EscortAI
-SD%Complete: 100
-SDComment:
-SDCategory: Npc
-EndScriptData */
-
#include "ScriptedEscortAI.h"
#include "Creature.h"
#include "Group.h"
#include "Log.h"
#include "Map.h"
#include "MotionMaster.h"
+#include "MovementGenerator.h"
#include "ObjectAccessor.h"
#include "Player.h"
+#include "ScriptSystem.h"
+#include "World.h"
enum Points
{
@@ -38,101 +34,75 @@ enum Points
POINT_HOME = 0xFFFFFE
};
-npc_escortAI::npc_escortAI(Creature* creature) : ScriptedAI(creature),
- m_uiWPWaitTimer(2500),
- m_uiPlayerCheckTimer(1000),
- m_uiEscortState(STATE_ESCORT_NONE),
- MaxPlayerDistance(DEFAULT_MAX_PLAYER_DISTANCE),
- m_pQuestForEscort(nullptr),
- m_bIsActiveAttacker(true),
- m_bIsRunning(false),
- m_bCanInstantRespawn(false),
- m_bCanReturnToStart(false),
- DespawnAtEnd(true),
- DespawnAtFar(true),
- ScriptWP(false),
- HasImmuneToNPCFlags(false)
-{ }
-
-void npc_escortAI::AttackStart(Unit* who)
+EscortAI::EscortAI(Creature* creature) : ScriptedAI(creature), _pauseTimer(2500), _playerCheckTimer(1000), _escortState(STATE_ESCORT_NONE), _maxPlayerDistance(DEFAULT_MAX_PLAYER_DISTANCE),
+ _escortQuest(nullptr), _activeAttacker(true), _running(false), _instantRespawn(false), _returnToStart(false), _despawnAtEnd(true), _despawnAtFar(true), _manualPath(false),
+ _hasImmuneToNPCFlags(false), _started(false), _ended(false), _resume(false)
{
- if (!who)
- return;
-
- if (me->Attack(who, true))
- {
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
- me->GetMotionMaster()->MovementExpired();
-
- if (IsCombatMovementAllowed())
- me->GetMotionMaster()->MoveChase(who);
- }
}
-Player* npc_escortAI::GetPlayerForEscort()
+Player* EscortAI::GetPlayerForEscort()
{
- return ObjectAccessor::GetPlayer(*me, m_uiPlayerGUID);
+ return ObjectAccessor::GetPlayer(*me, _playerGUID);
}
-//see followerAI
-bool npc_escortAI::AssistPlayerInCombatAgainst(Unit* who)
+// see followerAI
+bool EscortAI::AssistPlayerInCombatAgainst(Unit* who)
{
if (!who || !who->GetVictim())
return false;
- //experimental (unknown) flag not present
+ if (me->HasReactState(REACT_PASSIVE))
+ return false;
+
+ // experimental (unknown) flag not present
if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_ASSIST))
return false;
- //not a player
+ // not a player
if (!who->EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself())
return false;
- //never attack friendly
- if (me->IsFriendlyTo(who))
+ if (!who->isInAccessiblePlaceFor(me))
return false;
- //too far away and no free sight?
+ if (!CanAIAttack(who))
+ return false;
+
+ // we cannot attack in evade mode
+ if (me->IsInEvadeMode())
+ return false;
+
+ // or if enemy is in evade mode
+ if (who->GetTypeId() == TYPEID_UNIT && who->ToCreature()->IsInEvadeMode())
+ return false;
+
+ if (!me->IsValidAssistTarget(who->GetVictim()))
+ return false;
+
+ // too far away and no free sight
if (me->IsWithinDistInMap(who, GetMaxPlayerDistance()) && me->IsWithinLOSInMap(who))
{
- //already fighting someone?
- if (!me->GetVictim())
- {
- AttackStart(who);
- return true;
- }
- else
- {
- me->EngageWithTarget(who);
- return true;
- }
+ me->EngageWithTarget(who);
+ return true;
}
return false;
}
-void npc_escortAI::MoveInLineOfSight(Unit* who)
+void EscortAI::MoveInLineOfSight(Unit* who)
{
- if (me->HasReactState(REACT_AGGRESSIVE) && !me->HasUnitState(UNIT_STATE_STUNNED) && who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me))
- {
- if (HasEscortState(STATE_ESCORT_ESCORTING) && AssistPlayerInCombatAgainst(who))
- return;
+ if (!who)
+ return;
- if (!me->CanFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)
- return;
+ if (HasEscortState(STATE_ESCORT_ESCORTING) && AssistPlayerInCombatAgainst(who))
+ return;
- if (me->IsHostileTo(who))
- {
- float fAttackRadius = me->GetAttackDistance(who);
- if (me->IsWithinDistInMap(who, fAttackRadius) && me->IsWithinLOSInMap(who))
- me->EngageWithTarget(who);
- }
- }
+ ScriptedAI::MoveInLineOfSight(who);
}
-void npc_escortAI::JustDied(Unit* /*killer*/)
+void EscortAI::JustDied(Unit* /*killer*/)
{
- if (!HasEscortState(STATE_ESCORT_ESCORTING) || !m_uiPlayerGUID || !m_pQuestForEscort)
+ if (!HasEscortState(STATE_ESCORT_ESCORTING) || !_playerGUID || !_escortQuest)
return;
if (Player* player = GetPlayerForEscort())
@@ -140,24 +110,26 @@ void npc_escortAI::JustDied(Unit* /*killer*/)
if (Group* group = player->GetGroup())
{
for (GroupReference* groupRef = group->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next())
+ {
if (Player* member = groupRef->GetSource())
if (member->IsInMap(player))
- member->FailQuest(m_pQuestForEscort->GetQuestId());
+ member->FailQuest(_escortQuest->GetQuestId());
+ }
}
else
- player->FailQuest(m_pQuestForEscort->GetQuestId());
+ player->FailQuest(_escortQuest->GetQuestId());
}
}
-void npc_escortAI::JustRespawned()
+void EscortAI::JustAppeared()
{
- m_uiEscortState = STATE_ESCORT_NONE;
+ _escortState = STATE_ESCORT_NONE;
if (!IsCombatMovementAllowed())
SetCombatMovement(true);
- //add a small delay before going to first waypoint, normal in near all cases
- m_uiWPWaitTimer = 2500;
+ // add a small delay before going to first waypoint, normal in near all cases
+ _pauseTimer = 2000;
if (me->GetFaction() != me->GetCreatureTemplate()->faction)
me->RestoreFaction();
@@ -165,14 +137,12 @@ void npc_escortAI::JustRespawned()
Reset();
}
-void npc_escortAI::ReturnToLastPoint()
+void EscortAI::ReturnToLastPoint()
{
- float x, y, z, o;
- me->GetHomePosition(x, y, z, o);
- me->GetMotionMaster()->MovePoint(POINT_LAST_POINT, x, y, z);
+ me->GetMotionMaster()->MovePoint(POINT_LAST_POINT, me->GetHomePosition());
}
-void npc_escortAI::EnterEvadeMode(EvadeReason /*why*/)
+void EscortAI::EnterEvadeMode(EvadeReason /*why*/)
{
me->RemoveAllAuras();
me->GetThreatManager().ClearAllThreat();
@@ -183,27 +153,29 @@ void npc_escortAI::EnterEvadeMode(EvadeReason /*why*/)
{
AddEscortState(STATE_ESCORT_RETURNING);
ReturnToLastPoint();
- TC_LOG_DEBUG("scripts", "EscortAI has left combat and is now returning to last point");
+ TC_LOG_DEBUG("scripts", "EscortAI::EnterEvadeMode: left combat and is now returning to last point");
}
else
{
me->GetMotionMaster()->MoveTargetedHome();
- if (HasImmuneToNPCFlags)
+ if (_hasImmuneToNPCFlags)
me->SetImmuneToNPC(true);
Reset();
}
}
-bool npc_escortAI::IsPlayerOrGroupInRange()
+bool EscortAI::IsPlayerOrGroupInRange()
{
if (Player* player = GetPlayerForEscort())
{
if (Group* group = player->GetGroup())
{
for (GroupReference* groupRef = group->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next())
+ {
if (Player* member = groupRef->GetSource())
if (me->IsWithinDistInMap(member, GetMaxPlayerDistance()))
return true;
+ }
}
else if (me->IsWithinDistInMap(player, GetMaxPlayerDistance()))
return true;
@@ -212,95 +184,94 @@ bool npc_escortAI::IsPlayerOrGroupInRange()
return false;
}
-void npc_escortAI::UpdateAI(uint32 diff)
+void EscortAI::UpdateAI(uint32 diff)
{
- //Waypoint Updating
- if (HasEscortState(STATE_ESCORT_ESCORTING) && !me->GetVictim() && m_uiWPWaitTimer && !HasEscortState(STATE_ESCORT_RETURNING))
+ // Waypoint Updating
+ if (HasEscortState(STATE_ESCORT_ESCORTING) && !me->IsEngaged() && !HasEscortState(STATE_ESCORT_RETURNING))
{
- if (m_uiWPWaitTimer <= diff)
+ if (_pauseTimer <= diff)
{
- //End of the line
- if (CurrentWP == WaypointList.end())
+ if (!HasEscortState(STATE_ESCORT_PAUSED))
{
- if (DespawnAtEnd)
- {
- TC_LOG_DEBUG("scripts", "EscortAI reached end of waypoints");
-
- if (m_bCanReturnToStart)
- {
- float fRetX, fRetY, fRetZ;
- me->GetRespawnPosition(fRetX, fRetY, fRetZ);
-
- me->GetMotionMaster()->MovePoint(POINT_HOME, fRetX, fRetY, fRetZ);
+ _pauseTimer = 0;
- m_uiWPWaitTimer = 0;
-
- TC_LOG_DEBUG("scripts", "EscortAI are returning home to spawn location: %u, %f, %f, %f", POINT_HOME, fRetX, fRetY, fRetZ);
- return;
- }
+ if (_ended)
+ {
+ _ended = false;
+ me->GetMotionMaster()->MoveIdle();
- if (m_bCanInstantRespawn)
+ if (_despawnAtEnd)
{
- me->setDeathState(JUST_DIED);
- me->Respawn();
+ TC_LOG_DEBUG("scripts", "EscortAI::UpdateAI: reached end of waypoints, despawning at end");
+ if (_returnToStart)
+ {
+ Position respawnPosition;
+ float orientation = 0.f;
+ me->GetRespawnPosition(respawnPosition.m_positionX, respawnPosition.m_positionY, respawnPosition.m_positionZ, &orientation);
+ respawnPosition.SetOrientation(orientation);
+ me->GetMotionMaster()->MovePoint(POINT_HOME, respawnPosition);
+ TC_LOG_DEBUG("scripts", "EscortAI::UpdateAI: returning to spawn location: %s", respawnPosition.ToString().c_str());
+ }
+ else if (_instantRespawn)
+ me->Respawn(true);
+ else
+ me->DespawnOrUnsummon();
}
- else
- me->DespawnOrUnsummon();
-
+ TC_LOG_DEBUG("scripts", "EscortAI::UpdateAI: reached end of waypoints");
+ RemoveEscortState(STATE_ESCORT_ESCORTING);
return;
}
- else
- {
- TC_LOG_DEBUG("scripts", "EscortAI reached end of waypoints with Despawn off");
- return;
+ if (!_started)
+ {
+ _started = true;
+ me->GetMotionMaster()->MovePath(_path, false);
+ }
+ else if (_resume)
+ {
+ _resume = false;
+ if (MovementGenerator* movementGenerator = me->GetMotionMaster()->GetMotionSlot(MOTION_SLOT_IDLE))
+ movementGenerator->Resume(0);
}
- }
-
- if (!HasEscortState(STATE_ESCORT_PAUSED))
- {
- me->GetMotionMaster()->MovePoint(CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z);
- TC_LOG_DEBUG("scripts", "EscortAI start waypoint %u (%f, %f, %f).", CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z);
-
- WaypointStart(CurrentWP->id);
-
- m_uiWPWaitTimer = 0;
}
}
else
- m_uiWPWaitTimer -= diff;
+ _pauseTimer -= diff;
}
- //Check if player or any member of his group is within range
- if (HasEscortState(STATE_ESCORT_ESCORTING) && m_uiPlayerGUID && !me->GetVictim() && !HasEscortState(STATE_ESCORT_RETURNING))
+ // Check if player or any member of his group is within range
+ if (_despawnAtFar && HasEscortState(STATE_ESCORT_ESCORTING) && _playerGUID && !me->GetVictim() && !HasEscortState(STATE_ESCORT_RETURNING))
{
- if (m_uiPlayerCheckTimer <= diff)
+ if (_playerCheckTimer <= diff)
{
- if (DespawnAtFar && !IsPlayerOrGroupInRange())
+ if (!IsPlayerOrGroupInRange())
{
- TC_LOG_DEBUG("scripts", "EscortAI failed because player/group was to far away or not found");
+ TC_LOG_DEBUG("scripts", "EscortAI::UpdateAI: failed because player/group was to far away or not found");
- if (m_bCanInstantRespawn)
- {
- me->setDeathState(JUST_DIED);
- me->Respawn();
- }
+ bool isEscort = false;
+ if (CreatureData const* creatureData = me->GetCreatureData())
+ isEscort = (sWorld->getBoolConfig(CONFIG_RESPAWN_DYNAMIC_ESCORTNPC) && (creatureData->spawnGroupData->flags & SPAWNGROUP_FLAG_ESCORTQUESTNPC));
+
+ if (_instantRespawn && !isEscort)
+ me->DespawnOrUnsummon(0, Seconds(1));
+ else if (_instantRespawn && isEscort)
+ me->GetMap()->RemoveRespawnTime(SPAWN_TYPE_CREATURE, me->GetSpawnId(), true);
else
me->DespawnOrUnsummon();
return;
}
- m_uiPlayerCheckTimer = 1000;
+ _playerCheckTimer = 1000;
}
else
- m_uiPlayerCheckTimer -= diff;
+ _playerCheckTimer -= diff;
}
UpdateEscortAI(diff);
}
-void npc_escortAI::UpdateEscortAI(uint32 /*diff*/)
+void EscortAI::UpdateEscortAI(uint32 /*diff*/)
{
if (!UpdateVictim())
return;
@@ -308,262 +279,197 @@ void npc_escortAI::UpdateEscortAI(uint32 /*diff*/)
DoMeleeAttackIfReady();
}
-void npc_escortAI::MovementInform(uint32 moveType, uint32 pointId)
+void EscortAI::MovementInform(uint32 type, uint32 id)
{
- if (moveType != POINT_MOTION_TYPE || !HasEscortState(STATE_ESCORT_ESCORTING))
+ // no action allowed if there is no escort
+ if (!HasEscortState(STATE_ESCORT_ESCORTING))
return;
- //Combat start position reached, continue waypoint movement
- if (pointId == POINT_LAST_POINT)
+ if (type == POINT_MOTION_TYPE)
{
- TC_LOG_DEBUG("scripts", "EscortAI has returned to original position before combat");
+ if (!_pauseTimer)
+ _pauseTimer = 2000;
- me->SetWalk(!m_bIsRunning);
- RemoveEscortState(STATE_ESCORT_RETURNING);
-
- if (!m_uiWPWaitTimer)
- m_uiWPWaitTimer = 1;
+ // continue waypoint movement
+ if (id == POINT_LAST_POINT)
+ {
+ TC_LOG_DEBUG("scripts", "EscortAI::MovementInform: returned to before combat position");
+ me->SetWalk(!_running);
+ RemoveEscortState(STATE_ESCORT_RETURNING);
+ }
+ else if (id == POINT_HOME)
+ {
+ TC_LOG_DEBUG("scripts", "EscortAI::MovementInform: returned to home location and restarting waypoint path");
+ _started = false;
+ }
}
- else if (pointId == POINT_HOME)
+ else if (type == WAYPOINT_MOTION_TYPE)
{
- TC_LOG_DEBUG("scripts", "EscortAI has returned to original home location and will continue from beginning of waypoint list.");
+ ASSERT(id < _path.nodes.size(), "EscortAI::MovementInform: referenced movement id (%u) points to non-existing node in loaded path", id);
+ WaypointNode waypoint = _path.nodes[id];
- CurrentWP = WaypointList.begin();
- m_uiWPWaitTimer = 1;
- }
- else if (CurrentWP != WaypointList.end())
- {
- //Make sure that we are still on the right waypoint
- if (CurrentWP->id != pointId)
+ TC_LOG_DEBUG("scripts", "EscortAI::MovementInform: waypoint node %u reached", waypoint.id);
+
+ // last point
+ if (id == _path.nodes.size() - 1)
{
- TC_LOG_ERROR("misc", "TSCR ERROR: EscortAI reached waypoint out of order %u, expected %u, creature entry %u", pointId, CurrentWP->id, me->GetEntry());
- return;
+ _started = false;
+ _ended = true;
+ _pauseTimer = 1000;
}
-
- TC_LOG_DEBUG("scripts", "EscortAI Waypoint %u reached", CurrentWP->id);
-
- //Call WP function
- WaypointReached(CurrentWP->id);
-
- m_uiWPWaitTimer = CurrentWP->WaitTimeMs + 1;
-
- ++CurrentWP;
}
}
+///@todo investigate whether if its necessary to handle anything on charm
/*
-void npc_escortAI::OnPossess(bool apply)
+void EscortAI::OnCharmed(bool apply)
{
- // We got possessed in the middle of being escorted, store the point
- // where we left off to come back to when possess is removed
- if (HasEscortState(STATE_ESCORT_ESCORTING))
- {
- if (apply)
- me->GetPosition(LastPos.x, LastPos.y, LastPos.z);
- else
- {
- Returning = true;
- me->GetMotionMaster()->MovementExpired();
- me->GetMotionMaster()->MovePoint(WP_LAST_POINT, LastPos.x, LastPos.y, LastPos.z);
- }
- }
}
*/
-void npc_escortAI::AddWaypoint(uint32 id, float x, float y, float z, uint32 waitTime)
+void EscortAI::AddWaypoint(uint32 id, float x, float y, float z, float orientation/* = 0*/, uint32 waitTime/* = 0*/)
{
- Escort_Waypoint t(id, x, y, z, waitTime);
-
- WaypointList.push_back(t);
-
- // i think SD2 no longer uses this function
- ScriptWP = true;
- /*PointMovement wp;
- wp.m_uiCreatureEntry = me->GetEntry();
- wp.m_uiPointId = id;
- wp.m_fX = x;
- wp.m_fY = y;
- wp.m_fZ = z;
- wp.m_uiWaitTime = WaitTimeMs;
- PointMovementMap[wp.m_uiCreatureEntry].push_back(wp);*/
+ Trinity::NormalizeMapCoord(x);
+ Trinity::NormalizeMapCoord(y);
+
+ WaypointNode waypoint;
+ waypoint.id = id;
+ waypoint.x = x;
+ waypoint.y = y;
+ waypoint.z = z;
+ waypoint.orientation = orientation;
+ waypoint.moveType = _running ? WAYPOINT_MOVE_TYPE_RUN : WAYPOINT_MOVE_TYPE_WALK;
+ waypoint.delay = waitTime;
+ waypoint.eventId = 0;
+ waypoint.eventChance = 100;
+ _path.nodes.push_back(std::move(waypoint));
+
+ _manualPath = true;
}
-void npc_escortAI::FillPointMovementListForCreature()
+void EscortAI::FillPointMovementListForCreature()
{
- ScriptPointVector const* movePoints = sScriptSystemMgr->GetPointMoveList(me->GetEntry());
- if (!movePoints)
+ WaypointPath const* path = sScriptSystemMgr->GetPath(me->GetEntry());
+ if (!path)
return;
- for (ScriptPointVector::const_iterator itr = movePoints->begin(); itr != movePoints->end(); ++itr)
+ for (WaypointNode const& value : path->nodes)
{
- Escort_Waypoint point(itr->uiPointId, itr->fX, itr->fY, itr->fZ, itr->uiWaitTime);
- WaypointList.push_back(point);
+ WaypointNode node = value;
+ Trinity::NormalizeMapCoord(node.x);
+ Trinity::NormalizeMapCoord(node.y);
+ node.moveType = _running ? WAYPOINT_MOVE_TYPE_RUN : WAYPOINT_MOVE_TYPE_WALK;
+
+ _path.nodes.push_back(std::move(node));
}
}
-void npc_escortAI::SetRun(bool on)
+void EscortAI::SetRun(bool on)
{
- if (on)
- {
- if (!m_bIsRunning)
- me->SetWalk(false);
- else
- TC_LOG_DEBUG("scripts", "EscortAI attempt to set run mode, but is already running.");
- }
- else
- {
- if (m_bIsRunning)
- me->SetWalk(true);
- else
- TC_LOG_DEBUG("scripts", "EscortAI attempt to set walk mode, but is already walking.");
- }
+ if (on && !_running)
+ me->SetWalk(false);
+ else if (!on && _running)
+ me->SetWalk(true);
- m_bIsRunning = on;
+ _running = on;
}
/// @todo get rid of this many variables passed in function.
-void npc_escortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false */, ObjectGuid playerGUID /* = 0 */, Quest const* quest /* = nullptr */, bool instantRespawn /* = false */, bool canLoopPath /* = false */, bool resetWaypoints /* = true */)
+void EscortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false */, ObjectGuid playerGUID /* = 0 */, Quest const* quest /* = nullptr */, bool instantRespawn /* = false */, bool canLoopPath /* = false */, bool resetWaypoints /* = true */)
{
+ // Queue respawn from the point it starts
+ if (Map* map = me->GetMap())
+ {
+ if (CreatureData const* cdata = me->GetCreatureData())
+ {
+ if (SpawnGroupTemplateData const* groupdata = cdata->spawnGroupData)
+ {
+ if (sWorld->getBoolConfig(CONFIG_RESPAWN_DYNAMIC_ESCORTNPC) && (groupdata->flags & SPAWNGROUP_FLAG_ESCORTQUESTNPC) && !map->GetCreatureRespawnTime(me->GetSpawnId()))
+ {
+ me->SetRespawnTime(me->GetRespawnDelay());
+ me->SaveRespawnTime();
+ }
+ }
+ }
+ }
+
if (me->GetVictim())
{
- TC_LOG_ERROR("scripts.escortai", "TSCR ERROR: EscortAI (script: %s, creature entry: %u) attempts to Start while in combat", me->GetScriptName().c_str(), me->GetEntry());
+ TC_LOG_ERROR("scripts", "EscortAI::Start: (script: %s, creature entry: %u) attempts to Start while in combat", me->GetScriptName().c_str(), me->GetEntry());
return;
}
if (HasEscortState(STATE_ESCORT_ESCORTING))
{
- TC_LOG_ERROR("scripts.escortai", "EscortAI (script: %s, creature entry: %u) attempts to Start while already escorting", me->GetScriptName().c_str(), me->GetEntry());
+ TC_LOG_ERROR("scripts", "EscortAI::Start: (script: %s, creature entry: %u) attempts to Start while already escorting", me->GetScriptName().c_str(), me->GetEntry());
return;
}
- if (!ScriptWP && resetWaypoints) // sd2 never adds wp in script, but tc does
- {
- if (!WaypointList.empty())
- WaypointList.clear();
+ if (!_manualPath && resetWaypoints)
FillPointMovementListForCreature();
- }
- if (WaypointList.empty())
+ if (_path.nodes.empty())
{
- TC_LOG_ERROR("scripts", "EscortAI (script: %s, creature entry: %u) starts with 0 waypoints (possible missing entry in script_waypoint. Quest: %u).",
- me->GetScriptName().c_str(), me->GetEntry(), quest ? quest->GetQuestId() : 0);
+ TC_LOG_ERROR("scripts", "EscortAI::Start: (script: %s, creature entry: %u) starts with 0 waypoints (possible missing entry in script_waypoint. Quest: %u).", me->GetScriptName().c_str(), me->GetEntry(), quest ? quest->GetQuestId() : 0);
return;
}
- //set variables
- m_bIsActiveAttacker = isActiveAttacker;
- m_bIsRunning = run;
-
- m_uiPlayerGUID = playerGUID;
- m_pQuestForEscort = quest;
+ // set variables
+ _activeAttacker = isActiveAttacker;
+ _running = run;
+ _playerGUID = playerGUID;
+ _escortQuest = quest;
+ _instantRespawn = instantRespawn;
+ _returnToStart = canLoopPath;
- m_bCanInstantRespawn = instantRespawn;
- m_bCanReturnToStart = canLoopPath;
+ if (_returnToStart && _instantRespawn)
+ TC_LOG_DEBUG("scripts", "EscortAI::Start: (script: %s, creature entry: %u) is set to return home after waypoint end and instant respawn at waypoint end. Creature will never despawn.", me->GetScriptName().c_str(), me->GetEntry());
- if (m_bCanReturnToStart && m_bCanInstantRespawn)
- TC_LOG_DEBUG("scripts", "EscortAI is set to return home after waypoint end and instant respawn at waypoint end. Creature will never despawn.");
+ me->GetMotionMaster()->MoveIdle();
+ me->GetMotionMaster()->Clear(MOTION_SLOT_ACTIVE);
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
- {
- me->GetMotionMaster()->MovementExpired();
- me->GetMotionMaster()->MoveIdle();
- TC_LOG_DEBUG("scripts", "EscortAI start with WAYPOINT_MOTION_TYPE, changed to MoveIdle.");
- }
-
- //disable npcflags
+ // disable npcflags
me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
if (me->IsImmuneToNPC())
{
- HasImmuneToNPCFlags = true;
+ _hasImmuneToNPCFlags = true;
me->SetImmuneToNPC(false);
}
- TC_LOG_DEBUG("scripts", "EscortAI started with " UI64FMTD " waypoints. ActiveAttacker = %d, Run = %d, %s", uint64(WaypointList.size()), m_bIsActiveAttacker, m_bIsRunning, m_uiPlayerGUID.ToString().c_str());
+ TC_LOG_DEBUG("scripts", "EscortAI::Start: (script: %s, creature entry: %u) started with %u waypoints. ActiveAttacker = %d, Run = %d, Player = %s", me->GetScriptName().c_str(), me->GetEntry(), uint32(_path.nodes.size()), _activeAttacker, _running, _playerGUID.ToString().c_str());
- CurrentWP = WaypointList.begin();
-
- //Set initial speed
- if (m_bIsRunning)
- me->SetWalk(false);
- else
- me->SetWalk(true);
+ // set initial speed
+ me->SetWalk(!_running);
+ _started = false;
AddEscortState(STATE_ESCORT_ESCORTING);
}
-void npc_escortAI::SetEscortPaused(bool on)
+void EscortAI::SetEscortPaused(bool on)
{
if (!HasEscortState(STATE_ESCORT_ESCORTING))
return;
if (on)
- AddEscortState(STATE_ESCORT_PAUSED);
- else
- RemoveEscortState(STATE_ESCORT_PAUSED);
-}
-
-bool npc_escortAI::SetNextWaypoint(uint32 pointId, float x, float y, float z, float orientation)
-{
- me->UpdatePosition(x, y, z, orientation);
- return SetNextWaypoint(pointId, false, true);
-}
-
-bool npc_escortAI::SetNextWaypoint(uint32 pointId, bool setPosition, bool resetWaypointsOnFail)
-{
- if (!WaypointList.empty())
- WaypointList.clear();
-
- FillPointMovementListForCreature();
-
- if (WaypointList.empty())
- return false;
-
- size_t const size = WaypointList.size();
- Escort_Waypoint waypoint(0, 0, 0, 0, 0);
- do
{
- waypoint = WaypointList.front();
- WaypointList.pop_front();
- if (waypoint.id == pointId)
- {
- if (setPosition)
- me->UpdatePosition(waypoint.x, waypoint.y, waypoint.z, me->GetOrientation());
-
- CurrentWP = WaypointList.begin();
- return true;
- }
+ AddEscortState(STATE_ESCORT_PAUSED);
+ if (MovementGenerator* movementGenerator = me->GetMotionMaster()->GetMotionSlot(MOTION_SLOT_IDLE))
+ movementGenerator->Pause(0);
}
- while (!WaypointList.empty());
-
- // we failed.
- // we reset the waypoints in the start; if we pulled any, reset it again
- if (resetWaypointsOnFail && size != WaypointList.size())
+ else
{
- if (!WaypointList.empty())
- WaypointList.clear();
-
- FillPointMovementListForCreature();
+ RemoveEscortState(STATE_ESCORT_PAUSED);
+ _resume = true;
}
-
- return false;
}
-bool npc_escortAI::GetWaypointPosition(uint32 pointId, float& x, float& y, float& z)
+bool EscortAI::IsEscortNPC(bool onlyIfActive) const
{
- ScriptPointVector const* waypoints = sScriptSystemMgr->GetPointMoveList(me->GetEntry());
- if (!waypoints)
- return false;
+ if (!onlyIfActive)
+ return true;
- for (ScriptPointVector::const_iterator itr = waypoints->begin(); itr != waypoints->end(); ++itr)
- {
- if (itr->uiPointId == pointId)
- {
- x = itr->fX;
- y = itr->fY;
- z = itr->fZ;
- return true;
- }
- }
+ if (GetEventStarterGUID())
+ return true;
return false;
}
diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h
index 754d96dced9..4a514af33cc 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h
+++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h
@@ -20,93 +20,60 @@
#define SC_ESCORTAI_H
#include "ScriptedCreature.h"
-#include "ScriptSystem.h"
+#include "WaypointDefines.h"
class Quest;
#define DEFAULT_MAX_PLAYER_DISTANCE 50
-struct Escort_Waypoint
+enum EscortState : uint32
{
- Escort_Waypoint(uint32 _id, float _x, float _y, float _z, uint32 _w)
- {
- id = _id;
- x = _x;
- y = _y;
- z = _z;
- WaitTimeMs = _w;
- }
-
- uint32 id;
- float x;
- float y;
- float z;
- uint32 WaitTimeMs;
+ STATE_ESCORT_NONE = 0x00, // nothing in progress
+ STATE_ESCORT_ESCORTING = 0x01, // escort is in progress
+ STATE_ESCORT_RETURNING = 0x02, // escort is returning after being in combat
+ STATE_ESCORT_PAUSED = 0x04 // escort is paused, wont continue with next waypoint
};
-enum eEscortState
-{
- STATE_ESCORT_NONE = 0x000, //nothing in progress
- STATE_ESCORT_ESCORTING = 0x001, //escort are in progress
- STATE_ESCORT_RETURNING = 0x002, //escort is returning after being in combat
- STATE_ESCORT_PAUSED = 0x004 //will not proceed with waypoints before state is removed
-};
-
-struct TC_GAME_API npc_escortAI : public ScriptedAI
+struct TC_GAME_API EscortAI : public ScriptedAI
{
public:
- explicit npc_escortAI(Creature* creature);
- ~npc_escortAI() { }
-
- // CreatureAI functions
- void AttackStart(Unit* who) override;
+ explicit EscortAI(Creature* creature);
+ ~EscortAI() { }
+ void UpdateAI(uint32 diff) override; // the "internal" update, calls UpdateEscortAI()
void MoveInLineOfSight(Unit* who) override;
-
void JustDied(Unit*) override;
-
- void JustRespawned() override;
-
+ void JustAppeared() override;
void ReturnToLastPoint();
-
void EnterEvadeMode(EvadeReason /*why*/ = EVADE_REASON_OTHER) override;
-
- void UpdateAI(uint32 diff) override; // the "internal" update, calls UpdateEscortAI()
- virtual void UpdateEscortAI(uint32 diff); // used when it's needed to add code in update (abilities, scripted events, etc)
-
void MovementInform(uint32, uint32) override;
- // EscortAI functions
- void AddWaypoint(uint32 id, float x, float y, float z, uint32 waitTime = 0); // waitTime is in ms
-
- //this will set the current position to x/y/z/o, and the current WP to pointId.
- bool SetNextWaypoint(uint32 pointId, float x, float y, float z, float orientation);
+ virtual void UpdateEscortAI(uint32 diff); // used when it's needed to add code in update (abilities, scripted events, etc)
- //this will set the current position to WP start position (if setPosition == true),
- //and the current WP to pointId
- bool SetNextWaypoint(uint32 pointId, bool setPosition = true, bool resetWaypointsOnFail = true);
-
- bool GetWaypointPosition(uint32 pointId, float& x, float& y, float& z);
-
- virtual void WaypointReached(uint32 pointId) = 0;
- virtual void WaypointStart(uint32 /*pointId*/) { }
+ void AddWaypoint(uint32 id, float x, float y, float z, float orientation = 0.f, uint32 waitTime = 0); // waitTime is in ms
void Start(bool isActiveAttacker = true, bool run = false, ObjectGuid playerGUID = ObjectGuid::Empty, Quest const* quest = nullptr, bool instantRespawn = false, bool canLoopPath = false, bool resetWaypoints = true);
void SetRun(bool on = true);
+
void SetEscortPaused(bool on);
+ void SetPauseTimer(uint32 Timer) { _pauseTimer = Timer; }
+
+ bool HasEscortState(uint32 escortState) { return (_escortState & escortState) != 0; }
+ virtual bool IsEscorted() const override { return (_escortState & STATE_ESCORT_ESCORTING); }
+
+ void SetMaxPlayerDistance(float newMax) { _maxPlayerDistance = newMax; }
+ float GetMaxPlayerDistance() const { return _maxPlayerDistance; }
- bool HasEscortState(uint32 escortState) { return (m_uiEscortState & escortState) != 0; }
- virtual bool IsEscorted() const override { return (m_uiEscortState & STATE_ESCORT_ESCORTING); }
+ void SetDespawnAtEnd(bool despawn) { _despawnAtEnd = despawn; }
+ void SetDespawnAtFar(bool despawn) { _despawnAtFar = despawn; }
- void SetMaxPlayerDistance(float newMax) { MaxPlayerDistance = newMax; }
- float GetMaxPlayerDistance() const { return MaxPlayerDistance; }
+ bool GetAttack() const { return _activeAttacker; } // used in EnterEvadeMode override
+ void SetCanAttack(bool attack) { _activeAttacker = attack; }
- void SetDespawnAtEnd(bool despawn) { DespawnAtEnd = despawn; }
- void SetDespawnAtFar(bool despawn) { DespawnAtFar = despawn; }
- bool GetAttack() const { return m_bIsActiveAttacker; }//used in EnterEvadeMode override
- void SetCanAttack(bool attack) { m_bIsActiveAttacker = attack; }
- ObjectGuid GetEventStarterGUID() const { return m_uiPlayerGUID; }
+ ObjectGuid GetEventStarterGUID() const { return _playerGUID; }
+
+ virtual bool IsEscortNPC(bool isEscorting) const override;
protected:
Player* GetPlayerForEscort();
@@ -116,27 +83,29 @@ struct TC_GAME_API npc_escortAI : public ScriptedAI
bool IsPlayerOrGroupInRange();
void FillPointMovementListForCreature();
- void AddEscortState(uint32 escortState) { m_uiEscortState |= escortState; }
- void RemoveEscortState(uint32 escortState) { m_uiEscortState &= ~escortState; }
-
- ObjectGuid m_uiPlayerGUID;
- uint32 m_uiWPWaitTimer;
- uint32 m_uiPlayerCheckTimer;
- uint32 m_uiEscortState;
- float MaxPlayerDistance;
-
- Quest const* m_pQuestForEscort; //generally passed in Start() when regular escort script.
-
- std::list<Escort_Waypoint> WaypointList;
- std::list<Escort_Waypoint>::iterator CurrentWP;
-
- bool m_bIsActiveAttacker; //obsolete, determined by faction.
- bool m_bIsRunning; //all creatures are walking by default (has flag MOVEMENTFLAG_WALK)
- bool m_bCanInstantRespawn; //if creature should respawn instantly after escort over (if not, database respawntime are used)
- bool m_bCanReturnToStart; //if creature can walk same path (loop) without despawn. Not for regular escort quests.
- bool DespawnAtEnd;
- bool DespawnAtFar;
- bool ScriptWP;
- bool HasImmuneToNPCFlags;
+ void AddEscortState(uint32 escortState) { _escortState |= escortState; }
+ void RemoveEscortState(uint32 escortState) { _escortState &= ~escortState; }
+
+ ObjectGuid _playerGUID;
+ uint32 _pauseTimer;
+ uint32 _playerCheckTimer;
+ uint32 _escortState;
+ float _maxPlayerDistance;
+
+ Quest const* _escortQuest; // generally passed in Start() when regular escort script.
+
+ WaypointPath _path;
+
+ bool _activeAttacker; // obsolete, determined by faction.
+ bool _running; // all creatures are walking by default (has flag MOVEMENTFLAG_WALK)
+ bool _instantRespawn; // if creature should respawn instantly after escort over (if not, database respawntime are used)
+ bool _returnToStart; // if creature can walk same path (loop) without despawn. Not for regular escort quests.
+ bool _despawnAtEnd;
+ bool _despawnAtFar;
+ bool _manualPath;
+ bool _hasImmuneToNPCFlags;
+ bool _started;
+ bool _ended;
+ bool _resume;
};
#endif
diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
index b0b332afecd..6f50cdaac10 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
@@ -145,7 +145,7 @@ void FollowerAI::JustDied(Unit* /*killer*/)
}
}
-void FollowerAI::JustRespawned()
+void FollowerAI::JustAppeared()
{
m_uiFollowState = STATE_FOLLOW_NONE;
diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.h b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.h
index 7fe877a7589..1b13db8f7a3 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.h
+++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.h
@@ -41,8 +41,6 @@ class TC_GAME_API FollowerAI : public ScriptedAI
explicit FollowerAI(Creature* creature);
~FollowerAI() { }
- //virtual void WaypointReached(uint32 uiPointId) = 0;
-
void MovementInform(uint32 motionType, uint32 pointId) override;
void AttackStart(Unit*) override;
@@ -53,7 +51,7 @@ class TC_GAME_API FollowerAI : public ScriptedAI
void JustDied(Unit*) override;
- void JustRespawned() override;
+ void JustAppeared() override;
void UpdateAI(uint32) override; //the "internal" update, calls UpdateFollowerAI()
virtual void UpdateFollowerAI(uint32); //used when it's needed to add code in update (abilities, scripted events, etc)
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index 5aa2550a704..24719902659 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -17,6 +17,7 @@
#include "SmartAI.h"
#include "Creature.h"
+#include "CreatureGroups.h"
#include "DBCStructure.h"
#include "GameObject.h"
#include "Group.h"
@@ -28,54 +29,12 @@
#include "ScriptMgr.h"
#include "Vehicle.h"
-SmartAI::SmartAI(Creature* c) : CreatureAI(c)
+SmartAI::SmartAI(Creature* creature) : CreatureAI(creature), mIsCharmed(false), mFollowCreditType(0), mFollowArrivedTimer(0), mFollowCredit(0), mFollowArrivedEntry(0), mFollowDist(0.f), mFollowAngle(0.f),
+ _escortState(SMART_ESCORT_NONE), _escortNPCFlags(0), _escortInvokerCheckTimer(1000), _currentWaypointNode(0), _waypointReached(false), _waypointPauseTimer(0), _waypointPauseForced(false), _repeatWaypointPath(false),
+ _OOCReached(false), _waypointPathEnded(false), mRun(true), mEvadeDisabled(false), mCanAutoAttack(true), mCanCombatMove(true), mInvincibilityHpLevel(0), mDespawnTime(0), mDespawnState(0), mConditionsTimer(0),
+ _gossipReturn(false), mEscortQuestID(0)
{
- mIsCharmed = false;
- // copy script to local (protection for table reload)
-
- mWayPoints = nullptr;
- mEscortState = SMART_ESCORT_NONE;
- mCurrentWPID = 0;//first wp id is 1 !!
- mWPReached = false;
- mWPPauseTimer = 0;
- mEscortNPCFlags = 0;
- mLastWP = nullptr;
-
- mCanRepeatPath = false;
-
- // Spawn in run mode
- me->SetWalk(false);
- mRun = false;
- mEvadeDisabled = false;
-
- mLastOOCPos = me->GetPosition();
-
- mCanAutoAttack = true;
- mCanCombatMove = true;
-
- mForcedPaused = false;
- mLastWPIDReached = 0;
-
- mEscortQuestID = 0;
-
- mDespawnTime = 0;
- mDespawnState = 0;
-
- mEscortInvokerCheckTimer = 1000;
- mFollowGuid.Clear();
- mFollowDist = 0;
- mFollowAngle = 0;
- mFollowCredit = 0;
- mFollowArrivedEntry = 0;
- mFollowCreditType = 0;
- mFollowArrivedTimer = 0;
- mInvincibilityHpLevel = 0;
-
- mJustReset = false;
- mConditionsTimer = 0;
- mHasConditions = sConditionMgr->HasConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE, c->GetEntry());
-
- _gossipReturn = false;
+ mHasConditions = sConditionMgr->HasConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE, creature->GetEntry());
}
bool SmartAI::IsAIControlled() const
@@ -83,92 +42,68 @@ bool SmartAI::IsAIControlled() const
return !mIsCharmed;
}
-void SmartAI::UpdateDespawn(uint32 diff)
-{
- if (mDespawnState <= 1 || mDespawnState > 3)
- return;
-
- if (mDespawnTime < diff)
- {
- if (mDespawnState == 2)
- {
- me->SetVisible(false);
- mDespawnTime = 5000;
- mDespawnState++;
- }
- else
- me->DespawnOrUnsummon();
- } else mDespawnTime -= diff;
-}
-
-WayPoint* SmartAI::GetNextWayPoint()
-{
- if (!mWayPoints || mWayPoints->empty())
- return nullptr;
-
- mCurrentWPID++;
- WPPath::const_iterator itr = mWayPoints->find(mCurrentWPID);
- if (itr != mWayPoints->end())
- {
- mLastWP = (*itr).second;
- if (mLastWP->id != mCurrentWPID)
- {
- TC_LOG_ERROR("misc", "SmartAI::GetNextWayPoint: Got not expected waypoint id %u, expected %u", mLastWP->id, mCurrentWPID);
- }
- return (*itr).second;
- }
- return nullptr;
-}
-
-void SmartAI::StartPath(bool run, uint32 path, bool repeat, Unit* invoker)
+void SmartAI::StartPath(bool run/* = false*/, uint32 pathId/* = 0*/, bool repeat/* = false*/, Unit* invoker/* = nullptr*/, uint32 nodeId/* = 1*/)
{
- if (me->IsInCombat())// no wp movement in combat
+ if (me->IsInCombat()) // no wp movement in combat
{
- TC_LOG_ERROR("misc", "SmartAI::StartPath: Creature entry %u wanted to start waypoint movement while in combat, ignoring.", me->GetEntry());
+ TC_LOG_ERROR("misc", "SmartAI::StartPath: Creature entry %u wanted to start waypoint movement (%u) while in combat, ignoring.", me->GetEntry(), pathId);
return;
}
if (HasEscortState(SMART_ESCORT_ESCORTING))
StopPath();
- if (path)
+ SetRun(run);
+
+ if (pathId)
{
- if (!LoadPath(path))
+ if (!LoadPath(pathId))
return;
}
- if (!mWayPoints || mWayPoints->empty())
+ if (_path.nodes.empty())
return;
- if (WayPoint* wp = GetNextWayPoint())
- {
- AddEscortState(SMART_ESCORT_ESCORTING);
- mCanRepeatPath = repeat;
+ _currentWaypointNode = nodeId;
+ _waypointPathEnded = false;
- SetRun(run);
+ _repeatWaypointPath = repeat;
- if (invoker && invoker->GetTypeId() == TYPEID_PLAYER)
- {
- mEscortNPCFlags = me->GetUInt32Value(UNIT_NPC_FLAGS);
- me->SetUInt32Value(UNIT_NPC_FLAGS, 0);
- }
+ // Do not use AddEscortState, removing everything from previous
+ _escortState = SMART_ESCORT_ESCORTING;
- mLastOOCPos = me->GetPosition();
- me->GetMotionMaster()->MovePoint(wp->id, wp->x, wp->y, wp->z);
- GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_START, nullptr, wp->id, GetScript()->GetPathId());
+ if (invoker && invoker->GetTypeId() == TYPEID_PLAYER)
+ {
+ _escortNPCFlags = me->GetUInt32Value(UNIT_NPC_FLAGS);
+ me->SetFlag(UNIT_NPC_FLAGS, 0);
}
+
+ GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_START, nullptr, _currentWaypointNode, GetScript()->GetPathId());
+
+ me->GetMotionMaster()->MovePath(_path, _repeatWaypointPath);
}
bool SmartAI::LoadPath(uint32 entry)
{
if (HasEscortState(SMART_ESCORT_ESCORTING))
return false;
- mWayPoints = sSmartWaypointMgr->GetPath(entry);
- if (!mWayPoints)
+
+ WaypointPath const* path = sSmartWaypointMgr->GetPath(entry);
+ if (!path || path->nodes.empty())
{
GetScript()->SetPathId(0);
return false;
}
+
+ _path.id = path->id;
+ _path.nodes = path->nodes;
+ for (WaypointNode& waypoint : _path.nodes)
+ {
+ Trinity::NormalizeMapCoord(waypoint.x);
+ Trinity::NormalizeMapCoord(waypoint.y);
+ waypoint.moveType = mRun ? WAYPOINT_MOVE_TYPE_RUN : WAYPOINT_MOVE_TYPE_WALK;
+ }
+
GetScript()->SetPathId(entry);
return true;
}
@@ -176,65 +111,88 @@ bool SmartAI::LoadPath(uint32 entry)
void SmartAI::PausePath(uint32 delay, bool forced)
{
if (!HasEscortState(SMART_ESCORT_ESCORTING))
+ {
+ me->PauseMovement(delay, MOTION_SLOT_IDLE, forced);
+ if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
+ {
+ std::pair<uint32, uint32> waypointInfo = me->GetCurrentWaypointInfo();
+ GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_PAUSED, nullptr, waypointInfo.first, waypointInfo.second);
+ }
return;
+ }
+
if (HasEscortState(SMART_ESCORT_PAUSED))
{
- TC_LOG_ERROR("misc", "SmartAI::PausePath: Creature entry %u wanted to pause waypoint movement while already paused, ignoring.", me->GetEntry());
+ TC_LOG_ERROR("misc", "SmartAI::PausePath: Creature entry %u wanted to pause waypoint (current waypoint: %u) movement while already paused, ignoring.", me->GetEntry(), _currentWaypointNode);
return;
}
- mForcedPaused = forced;
- mLastOOCPos = me->GetPosition();
- AddEscortState(SMART_ESCORT_PAUSED);
- mWPPauseTimer = delay;
+
+ _waypointPauseTimer = delay;
+
if (forced)
{
+ _waypointPauseForced = forced;
SetRun(mRun);
- me->StopMoving();//force stop
- me->GetMotionMaster()->MoveIdle();//force stop
+ me->PauseMovement();
+ me->SetHomePosition(me->GetPosition());
}
- GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_PAUSED, nullptr, mLastWP->id, GetScript()->GetPathId());
+ else
+ _waypointReached = false;
+
+ AddEscortState(SMART_ESCORT_PAUSED);
+ GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_PAUSED, nullptr, _currentWaypointNode, GetScript()->GetPathId());
}
void SmartAI::StopPath(uint32 DespawnTime, uint32 quest, bool fail)
{
if (!HasEscortState(SMART_ESCORT_ESCORTING))
+ {
+ std::pair<uint32, uint32> waypointInfo = { 0, 0 };
+ if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
+ waypointInfo = me->GetCurrentWaypointInfo();
+
+ if (mDespawnState != 2)
+ SetDespawnTime(DespawnTime);
+
+ me->GetMotionMaster()->MoveIdle();
+
+ if (waypointInfo.first)
+ GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_STOPPED, nullptr, waypointInfo.first, waypointInfo.second);
+
+ if (!fail)
+ {
+ if (waypointInfo.first)
+ GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_ENDED, nullptr, waypointInfo.first, waypointInfo.second);
+ if (mDespawnState == 1)
+ StartDespawn();
+ }
return;
+ }
if (quest)
mEscortQuestID = quest;
- SetDespawnTime(DespawnTime);
- //mDespawnTime = DespawnTime;
- mLastOOCPos = me->GetPosition();
- me->StopMoving();//force stop
+ if (mDespawnState != 2)
+ SetDespawnTime(DespawnTime);
+
me->GetMotionMaster()->MoveIdle();
- GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_STOPPED, nullptr, mLastWP->id, GetScript()->GetPathId());
+
+ GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_STOPPED, nullptr, _currentWaypointNode, GetScript()->GetPathId());
+
EndPath(fail);
}
void SmartAI::EndPath(bool fail)
{
- GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_ENDED, nullptr, mLastWP->id, GetScript()->GetPathId());
-
RemoveEscortState(SMART_ESCORT_ESCORTING | SMART_ESCORT_PAUSED | SMART_ESCORT_RETURNING);
- mWayPoints = nullptr;
- mCurrentWPID = 0;
- mWPPauseTimer = 0;
- mLastWP = nullptr;
-
- if (mEscortNPCFlags)
- {
- me->SetUInt32Value(UNIT_NPC_FLAGS, mEscortNPCFlags);
- mEscortNPCFlags = 0;
- }
+ _path.nodes.clear();
+ _waypointPauseTimer = 0;
- if (mCanRepeatPath)
+ if (_escortNPCFlags)
{
- if (IsAIControlled())
- StartPath(mRun, GetScript()->GetPathId(), true);
+ me->SetFlag(UNIT_NPC_FLAGS, _escortNPCFlags);
+ _escortNPCFlags = 0;
}
- else
- GetScript()->SetPathId(0);
ObjectVector const* targets = GetScript()->GetStoredTargetVector(SMART_ESCORT_TARGETS, *me);
if (targets && mEscortQuestID)
@@ -279,126 +237,57 @@ void SmartAI::EndPath(bool fail)
}
}
+ // End Path events should be only processed if it was SUCCESSFUL stop or stop called by SMART_ACTION_WAYPOINT_STOP
+ if (fail)
+ return;
+
+ GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_ENDED, nullptr, _currentWaypointNode, GetScript()->GetPathId());
+
+ if (_repeatWaypointPath)
+ {
+ if (IsAIControlled())
+ StartPath(mRun, GetScript()->GetPathId(), _repeatWaypointPath);
+ }
+ else
+ GetScript()->SetPathId(0);
+
if (mDespawnState == 1)
StartDespawn();
}
void SmartAI::ResumePath()
{
- SetRun(mRun);
- if (mLastWP)
- me->GetMotionMaster()->MovePoint(mLastWP->id, mLastWP->x, mLastWP->y, mLastWP->z);
-}
+ GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_RESUMED, nullptr, _currentWaypointNode, GetScript()->GetPathId());
-void SmartAI::ReturnToLastOOCPos()
-{
- if (!IsAIControlled())
- return;
+ RemoveEscortState(SMART_ESCORT_PAUSED);
+
+ _waypointPauseForced = false;
+ _waypointReached = false;
+ _waypointPauseTimer = 0;
SetRun(mRun);
- me->GetMotionMaster()->MovePoint(SMART_ESCORT_LAST_OOC_POINT, mLastOOCPos);
+ me->ResumeMovement();
}
-void SmartAI::UpdatePath(const uint32 diff)
+void SmartAI::ReturnToLastOOCPos()
{
- if (!HasEscortState(SMART_ESCORT_ESCORTING))
- return;
- if (mEscortInvokerCheckTimer < diff)
- {
- // Escort failed, no players in range
- if (!IsEscortInvokerInRange())
- {
- StopPath(0, mEscortQuestID, true);
-
- // allow to properly hook out of range despawn action, which in most cases should perform the same operation as dying
- GetScript()->ProcessEventsFor(SMART_EVENT_DEATH, me);
- me->DespawnOrUnsummon(1);
- return;
- }
- mEscortInvokerCheckTimer = 1000;
- }
- else
- mEscortInvokerCheckTimer -= diff;
-
- // handle pause
- if (HasEscortState(SMART_ESCORT_PAUSED))
- {
- if (mWPPauseTimer < diff)
- {
- if (!me->IsInCombat() && !HasEscortState(SMART_ESCORT_RETURNING) && (mWPReached || mLastWPIDReached == SMART_ESCORT_LAST_OOC_POINT || mForcedPaused))
- {
- GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_RESUMED, nullptr, mLastWP->id, GetScript()->GetPathId());
- RemoveEscortState(SMART_ESCORT_PAUSED);
- if (mForcedPaused)// if paused between 2 wps resend movement
- {
- ResumePath();
- mWPReached = false;
- mForcedPaused = false;
- }
- if (mLastWPIDReached == SMART_ESCORT_LAST_OOC_POINT)
- mWPReached = true;
- }
-
- mWPPauseTimer = 0;
- }
- else
- mWPPauseTimer -= diff;
- }
-
- if (HasEscortState(SMART_ESCORT_RETURNING))
- {
- if (mWPReached)//reached OOC WP
- {
- RemoveEscortState(SMART_ESCORT_RETURNING);
- if (!HasEscortState(SMART_ESCORT_PAUSED))
- ResumePath();
- mWPReached = false;
- }
- }
-
- if ((!me->HasReactState(REACT_PASSIVE) && me->IsInCombat()) || HasEscortState(SMART_ESCORT_PAUSED | SMART_ESCORT_RETURNING))
+ if (!IsAIControlled())
return;
- // handle next wp
- if (mWPReached)//reached WP
- {
- mWPReached = false;
- if (mCurrentWPID == GetWPCount())
- {
- EndPath();
- }
- else if (WayPoint* wp = GetNextWayPoint())
- {
- SetRun(mRun);
- me->GetMotionMaster()->MovePoint(wp->id, wp->x, wp->y, wp->z);
- }
- }
+ me->SetWalk(false);
+ me->GetMotionMaster()->MovePoint(SMART_ESCORT_LAST_OOC_POINT, me->GetHomePosition());
}
void SmartAI::UpdateAI(uint32 diff)
{
CheckConditions(diff);
+
GetScript()->OnUpdate(diff);
+
UpdatePath(diff);
+ UpdateFollow(diff);
UpdateDespawn(diff);
- /// @todo move to void
- if (mFollowGuid)
- {
- if (mFollowArrivedTimer < diff)
- {
- if (me->FindNearestCreature(mFollowArrivedEntry, INTERACTION_DISTANCE, true))
- {
- StopFollow(true);
- return;
- }
-
- mFollowArrivedTimer = 1000;
- }
- else
- mFollowArrivedTimer -= diff;
- }
-
if (!IsAIControlled())
return;
@@ -450,24 +339,70 @@ bool SmartAI::IsEscortInvokerInRange()
return true;
}
-void SmartAI::MovepointReached(uint32 id)
+///@todo move escort related logic
+void SmartAI::WaypointPathStarted(uint32 nodeId, uint32 pathId)
+{
+ if (!HasEscortState(SMART_ESCORT_ESCORTING))
+ {
+ GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_START, nullptr, nodeId, pathId);
+ return;
+ }
+}
+
+///@todo Implement new smart event SMART_EVENT_WAYPOINT_STARTED
+void SmartAI::WaypointStarted(uint32 /*nodeId*/, uint32 /*pathId*/)
+{
+}
+
+void SmartAI::WaypointReached(uint32 nodeId, uint32 pathId)
{
- if (id != SMART_ESCORT_LAST_OOC_POINT && mLastWPIDReached != id)
- GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_REACHED, nullptr, id);
+ if (!HasEscortState(SMART_ESCORT_ESCORTING))
+ {
+ GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_REACHED, nullptr, nodeId, pathId);
+ return;
+ }
+
+ _currentWaypointNode = nodeId;
+
+ GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_REACHED, nullptr, _currentWaypointNode, pathId);
+
+ if (_waypointPauseTimer && !_waypointPauseForced)
+ {
+ _waypointReached = true;
+ me->PauseMovement();
+ me->SetHomePosition(me->GetPosition());
+ }
+ else if (HasEscortState(SMART_ESCORT_ESCORTING) && me->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
+ {
+ if (_currentWaypointNode == _path.nodes.size())
+ _waypointPathEnded = true;
+ else
+ SetRun(mRun);
+ }
+}
- mLastWPIDReached = id;
- mWPReached = true;
+///@todo move escort related logic
+void SmartAI::WaypointPathEnded(uint32 nodeId, uint32 pathId)
+{
+ if (!HasEscortState(SMART_ESCORT_ESCORTING))
+ {
+ GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_ENDED, nullptr, nodeId, pathId);
+ return;
+ }
}
-void SmartAI::MovementInform(uint32 MovementType, uint32 Data)
+void SmartAI::MovementInform(uint32 type, uint32 id)
{
- if ((MovementType == POINT_MOTION_TYPE && Data == SMART_ESCORT_LAST_OOC_POINT) || MovementType == FOLLOW_MOTION_TYPE)
+ if (type == POINT_MOTION_TYPE && id == SMART_ESCORT_LAST_OOC_POINT)
me->ClearUnitState(UNIT_STATE_EVADE);
- GetScript()->ProcessEventsFor(SMART_EVENT_MOVEMENTINFORM, nullptr, MovementType, Data);
- if (MovementType != POINT_MOTION_TYPE || !HasEscortState(SMART_ESCORT_ESCORTING))
+ GetScript()->ProcessEventsFor(SMART_EVENT_MOVEMENTINFORM, nullptr, type, id);
+
+ if (!HasEscortState(SMART_ESCORT_ESCORTING))
return;
- MovepointReached(Data);
+
+ if (type == POINT_MOTION_TYPE && id == SMART_ESCORT_LAST_OOC_POINT)
+ _OOCReached = true;
}
void SmartAI::EnterEvadeMode(EvadeReason /*why*/)
@@ -489,10 +424,16 @@ void SmartAI::EnterEvadeMode(EvadeReason /*why*/)
me->AddUnitState(UNIT_STATE_EVADE);
- GetScript()->ProcessEventsFor(SMART_EVENT_EVADE);//must be after aura clear so we can cast spells from db
+ GetScript()->ProcessEventsFor(SMART_EVENT_EVADE); // must be after _EnterEvadeMode (spells, auras, ...)
SetRun(mRun);
- if (HasEscortState(SMART_ESCORT_ESCORTING))
+
+ if (Unit* owner = me->GetCharmerOrOwner())
+ {
+ me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
+ me->ClearUnitState(UNIT_STATE_EVADE);
+ }
+ else if (HasEscortState(SMART_ESCORT_ESCORTING))
{
AddEscortState(SMART_ESCORT_RETURNING);
ReturnToLastOOCPos();
@@ -503,16 +444,11 @@ void SmartAI::EnterEvadeMode(EvadeReason /*why*/)
// evade is not cleared in MoveFollow, so we can't keep it
me->ClearUnitState(UNIT_STATE_EVADE);
}
- else if (Unit* owner = me->GetCharmerOrOwner())
- {
- me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
- me->ClearUnitState(UNIT_STATE_EVADE);
- }
else
me->GetMotionMaster()->MoveTargetedHome();
- if (!HasEscortState(SMART_ESCORT_ESCORTING)) //dont mess up escort movement after combat
- SetRun(mRun);
+ if (!me->HasUnitState(UNIT_STATE_EVADE))
+ GetScript()->OnReset();
}
void SmartAI::MoveInLineOfSight(Unit* who)
@@ -525,7 +461,7 @@ void SmartAI::MoveInLineOfSight(Unit* who)
if (!IsAIControlled())
return;
- if (AssistPlayerInCombatAgainst(who))
+ if (HasEscortState(SMART_ESCORT_ESCORTING) && AssistPlayerInCombatAgainst(who))
return;
CreatureAI::MoveInLineOfSight(who);
@@ -544,19 +480,32 @@ bool SmartAI::AssistPlayerInCombatAgainst(Unit* who)
if (!who || !who->GetVictim())
return false;
- //experimental (unknown) flag not present
+ // experimental (unknown) flag not present
if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_ASSIST))
return false;
- //not a player
+ // not a player
if (!who->EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself())
return false;
- //never attack friendly
+ if (!who->isInAccessiblePlaceFor(me))
+ return false;
+
+ if (!CanAIAttack(who))
+ return false;
+
+ // we cannot attack in evade mode
+ if (me->IsInEvadeMode())
+ return false;
+
+ // or if enemy is in evade mode
+ if (who->GetTypeId() == TYPEID_UNIT && who->ToCreature()->IsInEvadeMode())
+ return false;
+
if (!me->IsValidAssistTarget(who->GetVictim()))
return false;
- //too far away and no free sight?
+ // too far away and no free sight
if (me->IsWithinDistInMap(who, SMART_MAX_AID_DIST) && me->IsWithinLOSInMap(who))
{
me->EngageWithTarget(who);
@@ -566,18 +515,21 @@ bool SmartAI::AssistPlayerInCombatAgainst(Unit* who)
return false;
}
-void SmartAI::JustRespawned()
+void SmartAI::JustAppeared()
{
mDespawnTime = 0;
mDespawnState = 0;
- mEscortState = SMART_ESCORT_NONE;
+ _escortState = SMART_ESCORT_NONE;
+
me->SetVisible(true);
+
if (me->GetFaction() != me->GetCreatureTemplate()->faction)
me->RestoreFaction();
- mJustReset = true;
- JustReachedHome();
+
+ GetScript()->OnReset();
GetScript()->ProcessEventsFor(SMART_EVENT_RESPAWN);
- mFollowGuid.Clear();//do not reset follower on Reset(), we need it after combat evade
+
+ mFollowGuid.Clear(); // do not reset follower on Reset(), we need it after combat evade
mFollowDist = 0;
mFollowAngle = 0;
mFollowCredit = 0;
@@ -589,16 +541,18 @@ void SmartAI::JustRespawned()
void SmartAI::JustReachedHome()
{
GetScript()->OnReset();
+ GetScript()->ProcessEventsFor(SMART_EVENT_REACHED_HOME);
- if (!mJustReset)
+ CreatureGroup* formation = me->GetFormation();
+ if (!formation || formation->getLeader() == me || !formation->isFormed())
{
- GetScript()->ProcessEventsFor(SMART_EVENT_REACHED_HOME);
-
- if (!UpdateVictim() && me->GetMotionMaster()->GetCurrentMovementGeneratorType() == IDLE_MOTION_TYPE && me->GetWaypointPath())
+ if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_IDLE) != WAYPOINT_MOTION_TYPE && me->GetWaypointPath())
me->GetMotionMaster()->MovePath(me->GetWaypointPath(), true);
+ else
+ me->ResumeMovement();
}
-
- mJustReset = false;
+ else if (formation->isFormed())
+ me->GetMotionMaster()->MoveIdle(); // wait the order of leader
}
void SmartAI::EnterCombat(Unit* enemy)
@@ -607,24 +561,14 @@ void SmartAI::EnterCombat(Unit* enemy)
me->InterruptNonMeleeSpells(false); // must be before ProcessEvents
GetScript()->ProcessEventsFor(SMART_EVENT_AGGRO, enemy);
-
- if (!IsAIControlled())
- return;
- mLastOOCPos = me->GetPosition();
- SetRun(mRun);
- if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_ACTIVE) == POINT_MOTION_TYPE)
- me->GetMotionMaster()->MovementExpired();
}
void SmartAI::JustDied(Unit* killer)
{
- GetScript()->ProcessEventsFor(SMART_EVENT_DEATH, killer);
if (HasEscortState(SMART_ESCORT_ESCORTING))
- {
EndPath(true);
- me->StopMoving();//force stop
- me->GetMotionMaster()->MoveIdle();
- }
+
+ GetScript()->ProcessEventsFor(SMART_EVENT_DEATH, killer);
}
void SmartAI::KilledUnit(Unit* victim)
@@ -642,15 +586,21 @@ void SmartAI::AttackStart(Unit* who)
// dont allow charmed npcs to act on their own
if (!IsAIControlled())
{
- if (who && mCanAutoAttack)
- me->Attack(who, true);
+ if (who)
+ me->Attack(who, mCanAutoAttack);
return;
}
- if (who && me->Attack(who, me->IsWithinMeleeRange(who)))
+ if (who && me->Attack(who, mCanAutoAttack))
{
+ me->GetMotionMaster()->Clear(MOTION_SLOT_ACTIVE);
+ me->PauseMovement();
+
if (mCanCombatMove)
+ {
+ SetRun(mRun);
me->GetMotionMaster()->MoveChase(who);
+ }
}
}
@@ -713,12 +663,9 @@ void SmartAI::PassengerBoarded(Unit* who, int8 seatId, bool apply)
void SmartAI::InitializeAI()
{
GetScript()->OnInitialize(me);
+
if (!me->isDead())
- {
- mJustReset = true;
- JustReachedHome();
- GetScript()->ProcessEventsFor(SMART_EVENT_RESPAWN);
- }
+ GetScript()->OnReset();
}
void SmartAI::OnCharmed(bool apply)
@@ -727,13 +674,13 @@ void SmartAI::OnCharmed(bool apply)
{
if (HasEscortState(SMART_ESCORT_ESCORTING | SMART_ESCORT_PAUSED | SMART_ESCORT_RETURNING))
EndPath(true);
- me->StopMoving();
}
+
mIsCharmed = apply;
if (!apply && !me->IsInEvadeMode())
{
- if (mCanRepeatPath)
+ if (_repeatWaypointPath)
StartPath(mRun, GetScript()->GetPathId(), true);
else
me->SetWalk(!mRun);
@@ -826,30 +773,21 @@ void SmartAI::SetCombatMove(bool on)
{
if (mCanCombatMove == on)
return;
+
mCanCombatMove = on;
+
if (!IsAIControlled())
return;
- if (!HasEscortState(SMART_ESCORT_ESCORTING))
+
+ if (me->IsEngaged())
{
- if (on && me->GetVictim())
+ if (on && !me->HasReactState(REACT_PASSIVE) && me->GetVictim() && me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_ACTIVE) == MAX_MOTION_TYPE)
{
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == IDLE_MOTION_TYPE)
- {
- SetRun(mRun);
- me->GetMotionMaster()->MoveChase(me->GetVictim());
- me->CastStop();
- }
- }
- else
- {
- if (me->HasUnitState(UNIT_STATE_CONFUSED_MOVE | UNIT_STATE_FLEEING_MOVE))
- return;
-
- me->GetMotionMaster()->MovementExpired();
- me->GetMotionMaster()->Clear(true);
- me->StopMoving();
- me->GetMotionMaster()->MoveIdle();
+ SetRun(mRun);
+ me->GetMotionMaster()->MoveChase(me->GetVictim());
}
+ else if (!on && me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_ACTIVE) == CHASE_MOTION_TYPE)
+ me->GetMotionMaster()->Clear(MOTION_SLOT_ACTIVE);
}
}
@@ -881,7 +819,6 @@ void SmartAI::StopFollow(bool complete)
mFollowArrivedTimer = 1000;
mFollowArrivedEntry = 0;
mFollowCreditType = 0;
- me->StopMoving();
me->GetMotionMaster()->MoveIdle();
if (!complete)
@@ -949,6 +886,96 @@ void SmartAI::CheckConditions(uint32 diff)
mConditionsTimer -= diff;
}
+void SmartAI::UpdatePath(uint32 diff)
+{
+ if (!HasEscortState(SMART_ESCORT_ESCORTING))
+ return;
+
+ if (_escortInvokerCheckTimer < diff)
+ {
+ if (!IsEscortInvokerInRange())
+ {
+ StopPath(0, mEscortQuestID, true);
+
+ // allow to properly hook out of range despawn action, which in most cases should perform the same operation as dying
+ GetScript()->ProcessEventsFor(SMART_EVENT_DEATH, me);
+ me->DespawnOrUnsummon();
+ return;
+ }
+ _escortInvokerCheckTimer = 1000;
+ }
+ else
+ _escortInvokerCheckTimer -= diff;
+
+ // handle pause
+ if (HasEscortState(SMART_ESCORT_PAUSED) && (_waypointReached || _waypointPauseForced))
+ {
+ if (_waypointPauseTimer <= diff)
+ {
+ if (!me->IsInCombat() && !HasEscortState(SMART_ESCORT_RETURNING))
+ ResumePath();
+ }
+ else
+ _waypointPauseTimer -= diff;
+ }
+ else if (_waypointPathEnded) // end path
+ {
+ _waypointPathEnded = false;
+ StopPath();
+ return;
+ }
+
+ if (HasEscortState(SMART_ESCORT_RETURNING))
+ {
+ if (_OOCReached) // reached OOC WP
+ {
+ _OOCReached = false;
+ RemoveEscortState(SMART_ESCORT_RETURNING);
+ if (!HasEscortState(SMART_ESCORT_PAUSED))
+ ResumePath();
+ }
+ }
+}
+
+void SmartAI::UpdateFollow(uint32 diff)
+{
+ if (mFollowGuid)
+ {
+ if (mFollowArrivedTimer < diff)
+ {
+ if (me->FindNearestCreature(mFollowArrivedEntry, INTERACTION_DISTANCE, true))
+ {
+ StopFollow(true);
+ return;
+ }
+
+ mFollowArrivedTimer = 1000;
+ }
+ else
+ mFollowArrivedTimer -= diff;
+ }
+}
+
+void SmartAI::UpdateDespawn(uint32 diff)
+{
+ if (mDespawnState <= 1 || mDespawnState > 3)
+ return;
+
+ if (mDespawnTime < diff)
+ {
+ if (mDespawnState == 2)
+ {
+ me->SetVisible(false);
+ mDespawnTime = 5000;
+ mDespawnState++;
+ }
+ else
+ me->DespawnOrUnsummon();
+ }
+ else
+ mDespawnTime -= diff;
+}
+
void SmartGameObjectAI::UpdateAI(uint32 diff)
{
GetScript()->OnUpdate(diff);
@@ -957,10 +984,6 @@ void SmartGameObjectAI::UpdateAI(uint32 diff)
void SmartGameObjectAI::InitializeAI()
{
GetScript()->OnInitialize(me);
-
- // do not call respawn event if go is not spawned
- if (me->isSpawned())
- GetScript()->ProcessEventsFor(SMART_EVENT_RESPAWN);
//Reset();
}
diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h
index b5ed74c4edb..ecf9aaeb97a 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.h
+++ b/src/server/game/AI/SmartScripts/SmartAI.h
@@ -23,8 +23,7 @@
#include "GameObjectAI.h"
#include "Position.h"
#include "SmartScript.h"
-
-struct WayPoint;
+#include "WaypointDefines.h"
enum SmartEscortState
{
@@ -43,35 +42,42 @@ enum SmartEscortVars
class TC_GAME_API SmartAI : public CreatureAI
{
public:
- ~SmartAI(){ }
+ ~SmartAI() { }
explicit SmartAI(Creature* c);
+ // core related
+ static int32 Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; }
+
// Check whether we are currently permitted to make the creature take action
bool IsAIControlled() const;
// Start moving to the desired MovePoint
- void StartPath(bool run = false, uint32 path = 0, bool repeat = false, Unit* invoker = nullptr);
+ void StartPath(bool run = false, uint32 pathId = 0, bool repeat = false, Unit* invoker = nullptr, uint32 nodeId = 1);
bool LoadPath(uint32 entry);
void PausePath(uint32 delay, bool forced = false);
void StopPath(uint32 DespawnTime = 0, uint32 quest = 0, bool fail = false);
void EndPath(bool fail = false);
void ResumePath();
- WayPoint* GetNextWayPoint();
- bool HasEscortState(uint32 uiEscortState) const { return (mEscortState & uiEscortState) != 0; }
- void AddEscortState(uint32 uiEscortState) { mEscortState |= uiEscortState; }
- void RemoveEscortState(uint32 uiEscortState) { mEscortState &= ~uiEscortState; }
+ bool HasEscortState(uint32 uiEscortState) const { return (_escortState & uiEscortState) != 0; }
+ void AddEscortState(uint32 uiEscortState) { _escortState |= uiEscortState; }
+ void RemoveEscortState(uint32 uiEscortState) { _escortState &= ~uiEscortState; }
void SetAutoAttack(bool on) { mCanAutoAttack = on; }
void SetCombatMove(bool on);
bool CanCombatMove() { return mCanCombatMove; }
void SetFollow(Unit* target, float dist = 0.0f, float angle = 0.0f, uint32 credit = 0, uint32 end = 0, uint32 creditType = 0);
void StopFollow(bool complete);
+ bool IsEscortInvokerInRange();
+
+ void WaypointPathStarted(uint32 nodeId, uint32 pathId) override;
+ void WaypointStarted(uint32 nodeId, uint32 pathId) override;
+ void WaypointReached(uint32 nodeId, uint32 pathId) override;
+ void WaypointPathEnded(uint32 nodeId, uint32 pathId) override;
void SetScript9(SmartScriptHolder& e, uint32 entry, Unit* invoker);
SmartScript* GetScript() { return &mScript; }
- bool IsEscortInvokerInRange();
// Called when creature is spawned or respawned
- void JustRespawned() override;
+ void JustAppeared() override;
// Called at reaching home after evade, InitializeAI(), EnterEvadeMode() for resetting variables
void JustReachedHome() override;
@@ -157,12 +163,6 @@ class TC_GAME_API SmartAI : public CreatureAI
// Used in scripts to share variables
ObjectGuid GetGUID(int32 id = 0) const override;
- //core related
- static int32 Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; }
-
- // Called at movepoint reached
- void MovepointReached(uint32 id);
-
// Makes the creature run/walk
void SetRun(bool run = true);
@@ -183,8 +183,6 @@ class TC_GAME_API SmartAI : public CreatureAI
void QuestReward(Player* player, Quest const* quest, uint32 opt) override;
void OnGameEvent(bool start, uint16 eventId) override;
- uint32 mEscortQuestID;
-
void SetDespawnTime (uint32 t)
{
mDespawnTime = t;
@@ -194,11 +192,22 @@ class TC_GAME_API SmartAI : public CreatureAI
void OnSpellClick(Unit* clicker, bool& result) override;
- void SetWPPauseTimer(uint32 time) { mWPPauseTimer = time; }
+ void SetWPPauseTimer(uint32 time) { _waypointPauseTimer = time; }
void SetGossipReturn(bool val) { _gossipReturn = val; }
+ void SetEscortQuest(uint32 questID) { mEscortQuestID = questID; }
+
private:
+ bool AssistPlayerInCombatAgainst(Unit* who);
+ void ReturnToLastOOCPos();
+ void CheckConditions(uint32 diff);
+ void UpdatePath(uint32 diff);
+ void UpdateFollow(uint32 diff);
+ void UpdateDespawn(uint32 diff);
+
+ SmartScript mScript;
+
bool mIsCharmed;
uint32 mFollowCreditType;
uint32 mFollowArrivedTimer;
@@ -208,41 +217,35 @@ class TC_GAME_API SmartAI : public CreatureAI
float mFollowDist;
float mFollowAngle;
- void ReturnToLastOOCPos();
- void UpdatePath(const uint32 diff);
- SmartScript mScript;
- WPPath* mWayPoints;
- uint32 mEscortState;
- uint32 mCurrentWPID;
- uint32 mLastWPIDReached;
- bool mWPReached;
- uint32 mWPPauseTimer;
- uint32 mEscortNPCFlags;
- WayPoint* mLastWP;
- Position mLastOOCPos;//set on enter combat
- uint32 GetWPCount() const { return mWayPoints ? uint32(mWayPoints->size()) : 0; }
- bool mCanRepeatPath;
+ uint32 _escortState;
+ uint32 _escortNPCFlags;
+ uint32 _escortInvokerCheckTimer;
+ WaypointPath _path;
+ uint32 _currentWaypointNode;
+ bool _waypointReached;
+ uint32 _waypointPauseTimer;
+ bool _waypointPauseForced;
+ bool _repeatWaypointPath;
+ bool _OOCReached;
+ bool _waypointPathEnded;
+
bool mRun;
bool mEvadeDisabled;
bool mCanAutoAttack;
bool mCanCombatMove;
- bool mForcedPaused;
uint32 mInvincibilityHpLevel;
- bool AssistPlayerInCombatAgainst(Unit* who);
uint32 mDespawnTime;
uint32 mDespawnState;
- void UpdateDespawn(uint32 diff);
- uint32 mEscortInvokerCheckTimer;
- bool mJustReset;
// Vehicle conditions
- void CheckConditions(uint32 diff);
bool mHasConditions;
uint32 mConditionsTimer;
// Gossip
bool _gossipReturn;
+
+ uint32 mEscortQuestID;
};
class TC_GAME_API SmartGameObjectAI : public GameObjectAI
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index 7b7bb00416d..30fa5deadc3 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -39,6 +39,7 @@
#include "SpellMgr.h"
#include "TemporarySummon.h"
#include "Vehicle.h"
+#include "WaypointDefines.h"
#include <G3D/Quat.h>
SmartScript::SmartScript()
@@ -309,7 +310,11 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
if (IsUnit(target))
{
- target->PlayDirectSound(e.action.sound.sound, e.action.sound.onlySelf ? target->ToPlayer() : nullptr);
+ if (e.action.sound.distance == 1)
+ target->PlayDistanceSound(e.action.sound.sound, e.action.sound.onlySelf ? target->ToPlayer() : nullptr);
+ else
+ target->PlayDirectSound(e.action.sound.sound, e.action.sound.onlySelf ? target->ToPlayer() : nullptr);
+
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SOUND: target: %s (GuidLow: %u), sound: %u, onlyself: %u",
target->GetName().c_str(), target->GetGUID().GetCounter(), e.action.sound.sound, e.action.sound.onlySelf);
}
@@ -936,7 +941,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
case 1:
instance->SetBossState(e.action.setInstanceData.field, static_cast<EncounterState>(e.action.setInstanceData.data));
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_SET_INST_DATA: SetBossState BossId: %u, State: %u (%s)",
- e.action.setInstanceData.field, e.action.setInstanceData.data, InstanceScript::GetBossStateName(e.action.setInstanceData.data).c_str());
+ e.action.setInstanceData.field, e.action.setInstanceData.data, InstanceScript::GetBossStateName(e.action.setInstanceData.data));
break;
default: // Static analysis
break;
@@ -1039,8 +1044,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
else
creature->DespawnOrUnsummon(respawnDelay);
}
- else if (GameObject* go = target->ToGameObject())
- go->SetRespawnTime(respawnDelay);
+ else if (GameObject* goTarget = target->ToGameObject())
+ goTarget->SetRespawnTime(respawnDelay);
}
break;
}
@@ -1331,7 +1336,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
uint32 quest = e.action.wpStart.quest;
uint32 DespawnTime = e.action.wpStart.despawnTime;
- ENSURE_AI(SmartAI, me->AI())->mEscortQuestID = quest;
+ ENSURE_AI(SmartAI, me->AI())->SetEscortQuest(quest);
ENSURE_AI(SmartAI, me->AI())->SetDespawnTime(DespawnTime);
break;
}
@@ -1588,10 +1593,10 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (IsSmart(creature))
ENSURE_AI(SmartAI, creature->AI())->SetScript9(e, e.action.timedActionList.id, GetLastInvoker());
}
- else if (GameObject* go = target->ToGameObject())
+ else if (GameObject* goTarget = target->ToGameObject())
{
- if (IsSmartGO(go))
- ENSURE_AI(SmartGameObjectAI, go->AI())->SetScript9(e, e.action.timedActionList.id, GetLastInvoker());
+ if (IsSmartGO(goTarget))
+ ENSURE_AI(SmartGameObjectAI, goTarget->AI())->SetScript9(e, e.action.timedActionList.id, GetLastInvoker());
}
}
break;
@@ -1675,10 +1680,10 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (IsSmart(creature))
ENSURE_AI(SmartAI, creature->AI())->SetScript9(e, id, GetLastInvoker());
}
- else if (GameObject* go = target->ToGameObject())
+ else if (GameObject* goTarget = target->ToGameObject())
{
- if (IsSmartGO(go))
- ENSURE_AI(SmartGameObjectAI, go->AI())->SetScript9(e, id, GetLastInvoker());
+ if (IsSmartGO(goTarget))
+ ENSURE_AI(SmartGameObjectAI, goTarget->AI())->SetScript9(e, id, GetLastInvoker());
}
}
break;
@@ -1699,10 +1704,10 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (IsSmart(creature))
ENSURE_AI(SmartAI, creature->AI())->SetScript9(e, id, GetLastInvoker());
}
- else if (GameObject* go = target->ToGameObject())
+ else if (GameObject* goTarget = target->ToGameObject())
{
- if (IsSmartGO(go))
- ENSURE_AI(SmartGameObjectAI, go->AI())->SetScript9(e, id, GetLastInvoker());
+ if (IsSmartGO(goTarget))
+ ENSURE_AI(SmartGameObjectAI, goTarget->AI())->SetScript9(e, id, GetLastInvoker());
}
}
break;
@@ -1899,7 +1904,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
for (WorldObject* target : targets)
if (IsCreature(target))
- target->ToCreature()->setRegeneratingHealth(e.action.setHealthRegen.regenHealth != 0);
+ target->ToCreature()->SetRegenerateHealth(e.action.setHealthRegen.regenHealth != 0);
break;
}
case SMART_ACTION_SET_ROOT:
@@ -1990,7 +1995,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
std::back_inserter(waypoints), [](uint32 wp) { return wp != 0; });
float distanceToClosest = std::numeric_limits<float>::max();
- WayPoint* closestWp = nullptr;
+ std::pair<uint32, uint32> closest = { 0, 0 };
for (WorldObject* target : targets)
{
@@ -1998,29 +2003,27 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
if (IsSmart(creature))
{
- for (uint32 wp : waypoints)
+ for (uint32 pathId : waypoints)
{
- WPPath* path = sSmartWaypointMgr->GetPath(wp);
- if (!path || path->empty())
+ WaypointPath const* path = sSmartWaypointMgr->GetPath(pathId);
+ if (!path || path->nodes.empty())
continue;
- auto itrWp = path->find(0);
- if (itrWp != path->end())
+ for (auto itr = path->nodes.begin(); itr != path->nodes.end(); ++itr)
{
- if (WayPoint* wp = itrWp->second)
+ WaypointNode const waypoint = *itr;
+ float distamceToThisNode = creature->GetDistance(waypoint.x, waypoint.y, waypoint.z);
+ if (distamceToThisNode < distanceToClosest)
{
- float distToThisPath = creature->GetDistance(wp->x, wp->y, wp->z);
- if (distToThisPath < distanceToClosest)
- {
- distanceToClosest = distToThisPath;
- closestWp = wp;
- }
+ distanceToClosest = distamceToThisNode;
+ closest.first = pathId;
+ closest.second = waypoint.id;
}
}
}
- if (closestWp)
- CAST_AI(SmartAI, creature->AI())->StartPath(false, closestWp->id, true);
+ if (closest.first != 0)
+ ENSURE_AI(SmartAI, creature->AI())->StartPath(false, closest.first, true, nullptr, closest.second);
}
}
}
@@ -2038,7 +2041,12 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (IsUnit(target))
{
uint32 sound = Trinity::Containers::SelectRandomContainerElement(sounds);
- target->PlayDirectSound(sound, onlySelf ? target->ToPlayer() : nullptr);
+
+ if (e.action.randomSound.distance == 1)
+ target->PlayDistanceSound(sound, onlySelf ? target->ToPlayer() : nullptr);
+ else
+ target->PlayDirectSound(sound, onlySelf ? target->ToPlayer() : nullptr);
+
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_RANDOM_SOUND: target: %s (%s), sound: %u, onlyself: %s",
target->GetName().c_str(), target->GetGUID().ToString().c_str(), sound, onlySelf ? "true" : "false");
}
@@ -2052,6 +2060,92 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (IsCreature(target))
target->ToCreature()->SetCorpseDelay(e.action.corpseDelay.timer);
}
+
+ break;
+ }
+ case SMART_ACTION_SPAWN_SPAWNGROUP:
+ {
+ if (e.action.groupSpawn.minDelay == 0 && e.action.groupSpawn.maxDelay == 0)
+ {
+ bool const ignoreRespawn = ((e.action.groupSpawn.spawnflags & SMARTAI_SPAWN_FLAGS::SMARTAI_SPAWN_FLAG_IGNORE_RESPAWN) != 0);
+ bool const force = ((e.action.groupSpawn.spawnflags & SMARTAI_SPAWN_FLAGS::SMARTAI_SPAWN_FLAG_FORCE_SPAWN) != 0);
+
+ // Instant spawn
+ GetBaseObject()->GetMap()->SpawnGroupSpawn(e.action.groupSpawn.groupId, ignoreRespawn, force);
+ }
+ else
+ {
+ // Delayed spawn (use values from parameter to schedule event to call us back
+ SmartEvent ne = SmartEvent();
+ ne.type = (SMART_EVENT)SMART_EVENT_UPDATE;
+ ne.event_chance = 100;
+
+ ne.minMaxRepeat.min = e.action.groupSpawn.minDelay;
+ ne.minMaxRepeat.max = e.action.groupSpawn.maxDelay;
+ ne.minMaxRepeat.repeatMin = 0;
+ ne.minMaxRepeat.repeatMax = 0;
+
+ ne.event_flags = 0;
+ ne.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
+
+ SmartAction ac = SmartAction();
+ ac.type = (SMART_ACTION)SMART_ACTION_SPAWN_SPAWNGROUP;
+ ac.groupSpawn.groupId = e.action.groupSpawn.groupId;
+ ac.groupSpawn.minDelay = 0;
+ ac.groupSpawn.maxDelay = 0;
+ ac.groupSpawn.spawnflags = e.action.groupSpawn.spawnflags;
+ ac.timeEvent.id = e.action.timeEvent.id;
+
+ SmartScriptHolder ev = SmartScriptHolder();
+ ev.event = ne;
+ ev.event_id = e.event_id;
+ ev.target = e.target;
+ ev.action = ac;
+ InitTimer(ev);
+ mStoredEvents.push_back(ev);
+ }
+ break;
+ }
+ case SMART_ACTION_DESPAWN_SPAWNGROUP:
+ {
+ if (e.action.groupSpawn.minDelay == 0 && e.action.groupSpawn.maxDelay == 0)
+ {
+ bool const deleteRespawnTimes = ((e.action.groupSpawn.spawnflags & SMARTAI_SPAWN_FLAGS::SMARTAI_SPAWN_FLAG_NOSAVE_RESPAWN) != 0);
+
+ // Instant spawn
+ GetBaseObject()->GetMap()->SpawnGroupDespawn(e.action.groupSpawn.groupId, deleteRespawnTimes);
+ }
+ else
+ {
+ // Delayed spawn (use values from parameter to schedule event to call us back
+ SmartEvent ne = SmartEvent();
+ ne.type = (SMART_EVENT)SMART_EVENT_UPDATE;
+ ne.event_chance = 100;
+
+ ne.minMaxRepeat.min = e.action.groupSpawn.minDelay;
+ ne.minMaxRepeat.max = e.action.groupSpawn.maxDelay;
+ ne.minMaxRepeat.repeatMin = 0;
+ ne.minMaxRepeat.repeatMax = 0;
+
+ ne.event_flags = 0;
+ ne.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
+
+ SmartAction ac = SmartAction();
+ ac.type = (SMART_ACTION)SMART_ACTION_DESPAWN_SPAWNGROUP;
+ ac.groupSpawn.groupId = e.action.groupSpawn.groupId;
+ ac.groupSpawn.minDelay = 0;
+ ac.groupSpawn.maxDelay = 0;
+ ac.groupSpawn.spawnflags = e.action.groupSpawn.spawnflags;
+ ac.timeEvent.id = e.action.timeEvent.id;
+
+ SmartScriptHolder ev = SmartScriptHolder();
+ ev.event = ne;
+ ev.event_id = e.event_id;
+ ev.target = e.target;
+ ev.action = ac;
+ InitTimer(ev);
+ mStoredEvents.push_back(ev);
+ }
break;
}
case SMART_ACTION_DISABLE_EVADE:
@@ -2947,7 +3041,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
case SMART_EVENT_WAYPOINT_STOPPED:
case SMART_EVENT_WAYPOINT_ENDED:
{
- if (!me || (e.event.waypoint.pointID && var0 != e.event.waypoint.pointID) || (e.event.waypoint.pathID && GetPathId() != e.event.waypoint.pathID))
+ if (!me || (e.event.waypoint.pointID && var0 != e.event.waypoint.pointID) || (e.event.waypoint.pathID && var1 != e.event.waypoint.pathID))
return;
ProcessAction(e, unit);
break;
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
index 31282a934ac..b4713b7ed4d 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -29,6 +29,7 @@
#include "SpellMgr.h"
#include "Timer.h"
#include "UnitDefines.h"
+#include "WaypointDefines.h"
SmartWaypointMgr* SmartWaypointMgr::instance()
{
@@ -40,15 +41,7 @@ void SmartWaypointMgr::LoadFromDB()
{
uint32 oldMSTime = getMSTime();
- for (std::unordered_map<uint32, WPPath*>::iterator itr = waypoint_map.begin(); itr != waypoint_map.end(); ++itr)
- {
- for (WPPath::iterator pathItr = itr->second->begin(); pathItr != itr->second->end(); ++pathItr)
- delete pathItr->second;
-
- delete itr->second;
- }
-
- waypoint_map.clear();
+ _waypointStore.clear();
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_SMARTAI_WP);
PreparedQueryResult result = WorldDatabase.Query(stmt);
@@ -62,50 +55,47 @@ void SmartWaypointMgr::LoadFromDB()
uint32 count = 0;
uint32 total = 0;
- uint32 last_entry = 0;
- uint32 last_id = 1;
+ uint32 lastEntry = 0;
+ uint32 lastId = 1;
do
{
Field* fields = result->Fetch();
uint32 entry = fields[0].GetUInt32();
uint32 id = fields[1].GetUInt32();
- float x, y, z;
- x = fields[2].GetFloat();
- y = fields[3].GetFloat();
- z = fields[4].GetFloat();
+ float x = fields[2].GetFloat();
+ float y = fields[3].GetFloat();
+ float z = fields[4].GetFloat();
- if (last_entry != entry)
+ if (lastEntry != entry)
{
- waypoint_map[entry] = new WPPath();
- last_id = 1;
- count++;
+ lastId = 1;
+ ++count;
}
- if (last_id != id)
- TC_LOG_ERROR("sql.sql", "SmartWaypointMgr::LoadFromDB: Path entry %u, unexpected point id %u, expected %u.", entry, id, last_id);
+ if (lastId != id)
+ TC_LOG_ERROR("sql.sql", "SmartWaypointMgr::LoadFromDB: Path entry %u, unexpected point id %u, expected %u.", entry, id, lastId);
- last_id++;
- (*waypoint_map[entry])[id] = new WayPoint(id, x, y, z);
+ ++lastId;
+ WaypointPath& path = _waypointStore[entry];
+ path.id = entry;
+ path.nodes.emplace_back(id, x, y, z);
- last_entry = entry;
- total++;
+ lastEntry = entry;
+ ++total;
}
while (result->NextRow());
TC_LOG_INFO("server.loading", ">> Loaded %u SmartAI waypoint paths (total %u waypoints) in %u ms", count, total, GetMSTimeDiffToNow(oldMSTime));
}
-SmartWaypointMgr::~SmartWaypointMgr()
+WaypointPath const* SmartWaypointMgr::GetPath(uint32 id)
{
- for (std::unordered_map<uint32, WPPath*>::iterator itr = waypoint_map.begin(); itr != waypoint_map.end(); ++itr)
- {
- for (WPPath::iterator pathItr = itr->second->begin(); pathItr != itr->second->end(); ++pathItr)
- delete pathItr->second;
-
- delete itr->second;
- }
+ auto itr = _waypointStore.find(id);
+ if (itr != _waypointStore.end())
+ return &itr->second;
+ return nullptr;
}
SmartAIMgr* SmartAIMgr::instance()
@@ -228,7 +218,7 @@ void SmartAIMgr::LoadSmartAIFromDB()
}
case SMART_SCRIPT_TYPE_GAMEOBJECT:
{
- GameObjectData const* gameObject = sObjectMgr->GetGOData(uint32(std::abs(temp.entryOrGuid)));
+ GameObjectData const* gameObject = sObjectMgr->GetGameObjectData(uint32(std::abs(temp.entryOrGuid)));
if (!gameObject)
{
TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: GameObject guid (%u) does not exist, skipped loading.", uint32(std::abs(temp.entryOrGuid)));
@@ -932,7 +922,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
return false;
}
- if (e.event.distance.guid != 0 && !sObjectMgr->GetGOData(e.event.distance.guid))
+ if (e.event.distance.guid != 0 && !sObjectMgr->GetGameObjectData(e.event.distance.guid))
{
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_DISTANCE_GAMEOBJECT using invalid gameobject guid %u, skipped.", e.event.distance.guid);
return false;
@@ -1314,7 +1304,8 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
break;
case SMART_ACTION_WP_START:
{
- if (!sSmartWaypointMgr->GetPath(e.action.wpStart.pathID))
+ WaypointPath const* path = sSmartWaypointMgr->GetPath(e.action.wpStart.pathID);
+ if (!path || path->nodes.empty())
{
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Creature %d Event %u Action %u uses non-existent WaypointPath id %u, skipped.", e.entryOrGuid, e.event_id, e.GetActionType(), e.action.wpStart.pathID);
return false;
@@ -1508,6 +1499,8 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_ACTION_TRIGGER_RANDOM_TIMED_EVENT:
case SMART_ACTION_SET_COUNTER:
case SMART_ACTION_REMOVE_ALL_GAMEOBJECTS:
+ case SMART_ACTION_SPAWN_SPAWNGROUP:
+ case SMART_ACTION_DESPAWN_SPAWNGROUP:
break;
default:
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Not handled action_type(%u), event_type(%u), Entry %d SourceType %u Event %u, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id);
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index 7a1433bc7fb..499b1ad458e 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -20,6 +20,7 @@
#include "Define.h"
#include "ObjectGuid.h"
+#include "WaypointDefines.h"
#include <map>
#include <string>
#include <unordered_map>
@@ -27,22 +28,6 @@
class WorldObject;
enum SpellEffIndex : uint8;
-struct WayPoint
-{
- WayPoint(uint32 _id, float _x, float _y, float _z)
- {
- id = _id;
- x = _x;
- y = _y;
- z = _z;
- }
-
- uint32 id;
- float x;
- float y;
- float z;
-};
-
enum eSmartAI
{
SMART_EVENT_PARAM_COUNT = 4,
@@ -589,8 +574,12 @@ enum SMART_ACTION
SMART_ACTION_REMOVE_ALL_GAMEOBJECTS = 126,
SMART_ACTION_STOP_MOTION = 127, // stopMoving, movementExpired
SMART_ACTION_PLAY_ANIMKIT = 128, // don't use on 3.3.5a
+ SMART_ACTION_SCENE_PLAY = 129, // don't use on 3.3.5a
+ SMART_ACTION_SCENE_CANCEL = 130, // don't use on 3.3.5a
+ SMART_ACTION_SPAWN_SPAWNGROUP = 131, // Group ID, min secs, max secs, spawnflags
+ SMART_ACTION_DESPAWN_SPAWNGROUP = 132, // Group ID, min secs, max secs, spawnflags
- SMART_ACTION_END = 129
+ SMART_ACTION_END = 133
};
struct SmartAction
@@ -621,6 +610,7 @@ struct SmartAction
{
uint32 sound;
uint32 onlySelf;
+ uint32 distance;
} sound;
struct
@@ -1081,8 +1071,9 @@ struct SmartAction
struct
{
- uint32 sounds[SMART_ACTION_PARAM_COUNT - 1];
+ uint32 sounds[SMART_ACTION_PARAM_COUNT - 2];
uint32 onlySelf;
+ uint32 distance;
} randomSound;
struct
@@ -1094,6 +1085,13 @@ struct SmartAction
{
uint32 disable;
} disableEvade;
+ struct
+ {
+ uint32 groupId;
+ uint32 minDelay;
+ uint32 maxDelay;
+ uint32 spawnflags;
+ } groupSpawn;
struct
{
@@ -1138,6 +1136,14 @@ struct SmartAction
};
};
+enum SMARTAI_SPAWN_FLAGS
+{
+ SMARTAI_SPAWN_FLAG_NONE = 0x00,
+ SMARTAI_SPAWN_FLAG_IGNORE_RESPAWN = 0x01,
+ SMARTAI_SPAWN_FLAG_FORCE_SPAWN = 0x02,
+ SMARTAI_SPAWN_FLAG_NOSAVE_RESPAWN = 0x04,
+};
+
enum SMARTAI_TEMPLATE
{
SMARTAI_TEMPLATE_BASIC = 0, //nothing is preset
@@ -1495,8 +1501,6 @@ struct SmartScriptHolder
operator bool() const { return entryOrGuid != 0; }
};
-typedef std::unordered_map<uint32, WayPoint*> WPPath;
-
typedef std::vector<WorldObject*> ObjectVector;
class ObjectGuidVector
@@ -1523,26 +1527,22 @@ typedef std::unordered_map<uint32, ObjectGuidVector> ObjectVectorMap;
class TC_GAME_API SmartWaypointMgr
{
- private:
- SmartWaypointMgr() { }
- ~SmartWaypointMgr();
-
public:
static SmartWaypointMgr* instance();
void LoadFromDB();
- WPPath* GetPath(uint32 id)
- {
- if (waypoint_map.find(id) != waypoint_map.end())
- return waypoint_map[id];
- else return nullptr;
- }
+ WaypointPath const* GetPath(uint32 id);
private:
- std::unordered_map<uint32, WPPath*> waypoint_map;
+ SmartWaypointMgr() { }
+ ~SmartWaypointMgr() { }
+
+ std::unordered_map<uint32, WaypointPath> _waypointStore;
};
+#define sSmartWaypointMgr SmartWaypointMgr::instance()
+
// all events for a single entry
typedef std::vector<SmartScriptHolder> SmartAIEventList;
typedef std::vector<SmartScriptHolder> SmartAIEventStoredList;
@@ -1608,5 +1608,5 @@ class TC_GAME_API SmartAIMgr
};
#define sSmartScriptMgr SmartAIMgr::instance()
-#define sSmartWaypointMgr SmartWaypointMgr::instance()
+
#endif
diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h
index 8fc5f220d43..0f8e031ba20 100644
--- a/src/server/game/Accounts/RBAC.h
+++ b/src/server/game/Accounts/RBAC.h
@@ -57,7 +57,7 @@ enum RBACPermissions
RBAC_PERM_JOIN_RANDOM_BG = 4,
RBAC_PERM_JOIN_ARENAS = 5,
RBAC_PERM_JOIN_DUNGEON_FINDER = 6,
- // 7 - reuse
+ RBAC_PERM_IGNORE_IDLE_CONNECTION = 7,
// 8 - reuse
// 9 - reuse
RBAC_PERM_USE_CHARACTER_TEMPLATES = 10, // not on 3.3.5a
@@ -748,7 +748,7 @@ enum RBACPermissions
RBAC_PERM_COMMAND_SERVER_RESTART_FORCE = 840,
RBAC_PERM_COMMAND_NEARGRAVEYARD = 841,
RBAC_PERM_COMMAND_RELOAD_CHARACTER_TEMPLATE = 842, // not on 3.3.5a
- RBAC_PERM_COMMAND_RELOAD_QUEST_GREETING = 843, // not on 3.3.5a
+ RBAC_PERM_COMMAND_RELOAD_QUEST_GREETING = 843,
RBAC_PERM_COMMAND_SCENE = 844, // not on 3.3.5a
RBAC_PERM_COMMAND_SCENE_DEBUG = 845, // not on 3.3.5a
RBAC_PERM_COMMAND_SCENE_PLAY = 846, // not on 3.3.5a
@@ -761,16 +761,18 @@ enum RBACPermissions
RBAC_PERM_COMMAND_RELOAD_CONVERSATION_TEMPLATE = 853, // not on 3.3.5a
RBAC_PERM_COMMAND_DEBUG_CONVERSATION = 854, // not on 3.3.5a
RBAC_PERM_COMMAND_DEBUG_PLAY_MUSIC = 855,
- RBAC_PERM_COMMAND_NPC_SPAWNGROUP = 856, // reserved for dynamic_spawning
- RBAC_PERM_COMMAND_NPC_DESPAWNGROUP = 857, // reserved for dynamic_spawning
- RBAC_PERM_COMMAND_GOBJECT_SPAWNGROUP = 858, // reserved for dynamic_spawning
- RBAC_PERM_COMMAND_GOBJECT_DESPAWNGROUP = 859, // reserved for dynamic_spawning
- RBAC_PERM_COMMAND_LIST_RESPAWNS = 860, // reserved for dynamic_spawning
+ RBAC_PERM_COMMAND_NPC_SPAWNGROUP = 856,
+ RBAC_PERM_COMMAND_NPC_DESPAWNGROUP = 857,
+ RBAC_PERM_COMMAND_GOBJECT_SPAWNGROUP = 858,
+ RBAC_PERM_COMMAND_GOBJECT_DESPAWNGROUP = 859,
+ RBAC_PERM_COMMAND_LIST_RESPAWNS = 860,
RBAC_PERM_COMMAND_GROUP_SET = 861,
RBAC_PERM_COMMAND_GROUP_ASSISTANT = 862,
RBAC_PERM_COMMAND_GROUP_MAINTANK = 863,
RBAC_PERM_COMMAND_GROUP_MAINASSIST = 864,
RBAC_PERM_COMMAND_NPC_SHOWLOOT = 865,
+ RBAC_PERM_COMMAND_LIST_SPAWNPOINTS = 866,
+ RBAC_PERM_COMMAND_RELOAD_QUEST_GREETING_LOCALE = 867,
// custom permissions 1000+
RBAC_PERM_MAX
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index a43ef238521..f904614960a 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -2287,7 +2287,7 @@ void AchievementGlobalMgr::LoadAchievementCriteriaList()
if (sAchievementCriteriaStore.GetNumRows() == 0)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 achievement criteria.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 achievement criteria.");
return;
}
@@ -2574,7 +2574,7 @@ void AchievementGlobalMgr::LoadRewards()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 achievement rewards. DB table `achievement_reward` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 achievement rewards. DB table `achievement_reward` is empty.");
return;
}
diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp
index 27e83185e27..92b78216cb0 100644
--- a/src/server/game/Battlefield/Battlefield.cpp
+++ b/src/server/game/Battlefield/Battlefield.cpp
@@ -776,18 +776,15 @@ Creature* Battlefield::SpawnCreature(uint32 entry, Position const& pos)
return nullptr;
}
- float x, y, z, o;
- pos.GetPosition(x, y, z, o);
-
Creature* creature = new Creature();
- if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, PHASEMASK_NORMAL, entry, x, y, z, o))
+ if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, PHASEMASK_NORMAL, entry, pos))
{
TC_LOG_ERROR("bg.battlefield", "Battlefield::SpawnCreature: Can't create creature entry: %u", entry);
delete creature;
return nullptr;
}
- creature->SetHomePosition(x, y, z, o);
+ creature->SetHomePosition(pos);
// Set creature in world
map->AddToMap(creature);
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index 41591c419e9..e184c22354e 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -1515,7 +1515,7 @@ Creature* Battleground::AddCreature(uint32 entry, uint32 type, float x, float y,
Creature* creature = new Creature();
- if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, PHASEMASK_NORMAL, entry, x, y, z, o))
+ if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, PHASEMASK_NORMAL, entry, { x, y, z, o }))
{
TC_LOG_ERROR("bg.battleground", "Battleground::AddCreature: cannot create creature (entry: %u) for BG (map: %u, instance id: %u)!",
entry, m_MapId, m_InstanceID);
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
index 1b8fb8ee907..76e3d7ea08c 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
@@ -535,7 +535,7 @@ void BattlegroundMgr::LoadBattlegroundTemplates()
QueryResult result = WorldDatabase.Query("SELECT ID, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, AllianceStartLoc, AllianceStartO, HordeStartLoc, HordeStartO, StartMaxDist, Weight, ScriptName FROM battleground_template");
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 battlegrounds. DB table `battleground_template` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 battlegrounds. DB table `battleground_template` is empty.");
return;
}
@@ -973,7 +973,6 @@ BattlegroundTypeId BattlegroundMgr::GetRandomBG(BattlegroundTypeId bgTypeId)
{
if (BattlegroundTemplate const* bgTemplate = GetBattlegroundTemplateByTypeId(bgTypeId))
{
- BattlegroundSelectionWeightMap selectionWeights;
std::vector<BattlegroundTypeId> ids;
ids.reserve(16);
std::vector<double> weights;
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
index 6ef3bbcc3c3..3ebca71a326 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
@@ -176,7 +176,7 @@ void BattlegroundAB::PostUpdateImpl(uint32 diff)
if (team == TEAM_ALLIANCE)
UpdateWorldState(BG_AB_OP_RESOURCES_ALLY, m_TeamScores[team]);
- else if (team == TEAM_HORDE)
+ else
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
@@ -418,12 +418,12 @@ void BattlegroundAB::_NodeOccupied(uint8 node, Team team)
void BattlegroundAB::_NodeDeOccupied(uint8 node)
{
+ //only dynamic nodes, no start points
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
+ DelCreature(node+7);//NULL checks are in DelCreature! 0-6 spirit guides
RelocateDeadPlayers(BgCreatures[node]);
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h
index 7f68ef3eb0d..f7215989093 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h
@@ -212,11 +212,11 @@ const uint32 BG_AB_GraveyardIds[BG_AB_ALL_NODES_COUNT] = {895, 894, 893, 897, 89
// 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
+ {1185.566f, 1184.629f, -56.36329f, 2.303831f}, // stables
+ {990.1131f, 1008.73f, -42.60328f, 0.8203033f}, // blacksmith
+ {818.0089f, 842.3543f, -56.54062f, 3.176533f}, // farm
+ {808.8463f, 1185.417f, 11.92161f, 5.619962f}, // lumber mill
+ {1147.091f, 816.8362f, -98.39896f, 6.056293f} // gold mine
};
Position const BG_AB_SpiritGuidePos[BG_AB_ALL_NODES_COUNT] =
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
index fc2bee156ee..506e4d2dea3 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
@@ -314,6 +314,7 @@ Creature* BattlegroundAV::AddAVCreature(uint16 cinfoid, uint16 type)
|| (cinfoid >= AV_NPC_H_GRAVEDEFENSE0 && cinfoid <= AV_NPC_H_GRAVEDEFENSE3)))
{
CreatureData &data = sObjectMgr->NewOrExistCreatureData(creature->GetSpawnId());
+ data.spawnGroupData = sObjectMgr->GetDefaultSpawnGroup();
data.spawndist = 5;
}
//else spawndist will be 15, so creatures move maximum=10
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h
index 9adaea025d3..7336caaf0d7 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h
@@ -987,19 +987,19 @@ Position const BG_AV_CreaturePos[AV_CPLACE_MAX] =
enum BG_AV_CreatureIds
{
- AV_NPC_A_TOWERDEFENSE = 0, // stormpike bowman
- AV_NPC_A_GRAVEDEFENSE0 = 1, // stormpike Defender
- AV_NPC_A_GRAVEDEFENSE1 = 2, // seasoned defender
- AV_NPC_A_GRAVEDEFENSE2 = 3, // veteran defender
- AV_NPC_A_GRAVEDEFENSE3 = 4, // champion defender
+ 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_TOWERDEFENSE = 7, // frostwolf bowman
- AV_NPC_H_GRAVEDEFENSE0 = 8, // frostwolf guardian
- AV_NPC_H_GRAVEDEFENSE1 = 9, // seasoned guardian
- AV_NPC_H_GRAVEDEFENSE2 = 10, // veteran guardian
- AV_NPC_H_GRAVEDEFENSE3 = 11, // champion guardian
+ 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
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
index e1d1394cb05..a686d52cda2 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
@@ -529,8 +529,7 @@ bool BattlegroundEY::SetupBattleground()
TC_LOG_ERROR("bg.battleground", "BattlegroundEY: Could not spawn Speedbuff Fel Reaver.");
}
- WorldSafeLocsEntry const* sg = nullptr;
- sg = sWorldSafeLocsStore.LookupEntry(EY_GRAVEYARD_MAIN_ALLIANCE);
+ WorldSafeLocsEntry const* sg = sWorldSafeLocsStore.LookupEntry(EY_GRAVEYARD_MAIN_ALLIANCE);
if (!sg || !AddSpiritGuide(EY_SPIRIT_MAIN_ALLIANCE, sg->x, sg->y, sg->z, 3.124139f, TEAM_ALLIANCE))
{
TC_LOG_ERROR("sql.sql", "BatteGroundEY: Failed to spawn spirit guide. The battleground was not created.");
@@ -774,8 +773,7 @@ void BattlegroundEY::EventTeamCapturedPoint(Player* player, uint32 Point)
if (BgCreatures[Point])
DelCreature(Point);
- WorldSafeLocsEntry const* sg = nullptr;
- sg = sWorldSafeLocsStore.LookupEntry(m_CapturingPointTypes[Point].GraveyardId);
+ WorldSafeLocsEntry const* sg = sWorldSafeLocsStore.LookupEntry(m_CapturingPointTypes[Point].GraveyardId);
if (!sg || !AddSpiritGuide(Point, sg->x, sg->y, sg->z, 3.124139f, GetTeamIndexByTeamId(Team)))
TC_LOG_ERROR("bg.battleground", "BatteGroundEY: Failed to spawn spirit guide. point: %u, team: %u, graveyard_id: %u",
Point, Team, m_CapturingPointTypes[Point].GraveyardId);
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
index b28f31cd09c..90fd95b5780 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
@@ -198,8 +198,7 @@ bool BattlegroundSA::ResetObjs()
//Graveyards
for (uint8 i = 0; i < BG_SA_MAX_GY; i++)
{
- WorldSafeLocsEntry const* sg = nullptr;
- sg = sWorldSafeLocsStore.LookupEntry(BG_SA_GYEntries[i]);
+ WorldSafeLocsEntry const* sg = sWorldSafeLocsStore.LookupEntry(BG_SA_GYEntries[i]);
if (!sg)
{
diff --git a/src/server/game/Calendar/CalendarMgr.cpp b/src/server/game/Calendar/CalendarMgr.cpp
index 08a406c4f15..d93786d66f1 100644
--- a/src/server/game/Calendar/CalendarMgr.cpp
+++ b/src/server/game/Calendar/CalendarMgr.cpp
@@ -57,6 +57,8 @@ CalendarMgr* CalendarMgr::instance()
void CalendarMgr::LoadFromDB()
{
+ uint32 oldMSTime = getMSTime();
+
uint32 count = 0;
_maxEventId = 0;
_maxInviteId = 0;
@@ -90,7 +92,7 @@ void CalendarMgr::LoadFromDB()
}
while (result->NextRow());
- TC_LOG_INFO("server.loading", ">> Loaded %u calendar events", count);
+ TC_LOG_INFO("server.loading", ">> Loaded %u calendar events in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
count = 0;
// 0 1 2 3 4 5 6 7
@@ -117,7 +119,7 @@ void CalendarMgr::LoadFromDB()
}
while (result->NextRow());
- TC_LOG_INFO("server.loading", ">> Loaded %u calendar invites", count);
+ TC_LOG_INFO("server.loading", ">> Loaded %u calendar invites in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
for (uint64 i = 1; i < _maxEventId; ++i)
if (!GetEvent(i))
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
index 3e15ecc9319..46c6a26760c 100644
--- a/src/server/game/Chat/Chat.cpp
+++ b/src/server/game/Chat/Chat.cpp
@@ -33,6 +33,7 @@
#include "Realm.h"
#include "ScriptMgr.h"
#include "World.h"
+#include <boost/algorithm/string/replace.hpp>
ChatCommand::ChatCommand(char const* name, uint32 permission, bool allowConsole, pHandler handler, std::string help, std::vector<ChatCommand> childCommands /*= std::vector<ChatCommand>()*/)
: Name(ASSERT_NOTNULL(name)), Permission(permission), AllowConsole(allowConsole), Handler(handler), Help(std::move(help)), ChildCommands(std::move(childCommands))
@@ -347,6 +348,7 @@ bool ChatHandler::ExecuteCommandInTable(std::vector<ChatCommand> const& table, c
SendSysMessage(table[i].Help.c_str());
else
SendSysMessage(LANG_CMD_SYNTAX);
+ SetSentErrorMessage(true);
}
return true;
@@ -410,41 +412,39 @@ bool ChatHandler::SetDataForCommandInTable(std::vector<ChatCommand>& table, char
return false;
}
+bool ChatHandler::_ParseCommands(char const* text)
+{
+ if (ExecuteCommandInTable(getCommandTable(), text, text))
+ return true;
+
+ // Pretend commands don't exist for regular players
+ if (m_session && !m_session->HasPermission(rbac::RBAC_PERM_COMMANDS_NOTIFY_COMMAND_NOT_FOUND_ERROR))
+ return false;
+
+ // Send error message for GMs
+ SendSysMessage(LANG_NO_CMD);
+ SetSentErrorMessage(true);
+ return true;
+}
+
bool ChatHandler::ParseCommands(char const* text)
{
ASSERT(text);
ASSERT(*text);
- std::string fullcmd = text;
-
/// chat case (.command or !command format)
- if (m_session)
- {
- if (text[0] != '!' && text[0] != '.')
- return false;
- }
+ if (text[0] != '!' && text[0] != '.')
+ return false;
/// ignore single . and ! in line
- if (strlen(text) < 2)
+ if (!text[1])
return false;
- // original `text` can't be used. It content destroyed in command code processing.
/// ignore messages staring from many dots.
- if ((text[0] == '.' && text[1] == '.') || (text[0] == '!' && text[1] == '!'))
+ if (text[1] == '!' || text[1] == '.')
return false;
- /// skip first . or ! (in console allowed use command with . and ! and without its)
- if (text[0] == '!' || text[0] == '.')
- ++text;
-
- if (!ExecuteCommandInTable(getCommandTable(), text, fullcmd))
- {
- if (m_session && !m_session->HasPermission(rbac::RBAC_PERM_COMMANDS_NOTIFY_COMMAND_NOT_FOUND_ERROR))
- return false;
-
- SendSysMessage(LANG_NO_CMD);
- }
- return true;
+ return _ParseCommands(text+1);
}
bool ChatHandler::isValidChatMessage(char const* message)
@@ -1232,6 +1232,16 @@ void CliHandler::SendSysMessage(const char *str, bool /*escapeCharacters*/)
m_print(m_callbackArg, "\r\n");
}
+bool CliHandler::ParseCommands(char const* str)
+{
+ if (!str[0])
+ return false;
+ // Console allows using commands both with and without leading indicator
+ if (str[0] == '.' || str[0] == '!')
+ ++str;
+ return _ParseCommands(str);
+}
+
std::string CliHandler::GetNameLink() const
{
return GetTrinityString(LANG_CONSOLE_COMMAND);
@@ -1295,3 +1305,102 @@ int CliHandler::GetSessionDbLocaleIndex() const
{
return sObjectMgr->GetDBCLocaleIndex();
}
+
+bool AddonChannelCommandHandler::ParseCommands(char const* str)
+{
+ if (memcmp(str, "TrinityCore\t", 12))
+ return false;
+ char opcode = str[12];
+ if (!opcode) // str[12] is opcode
+ return false;
+ if (!str[13] || !str[14] || !str[15] || !str[16]) // str[13] through str[16] is 4-character command counter
+ return false;
+ echo = str+13;
+
+ switch (opcode)
+ {
+ case 'p': // p Ping
+ SendAck();
+ return true;
+ case 'h': // h Issue human-readable command
+ case 'i': // i Issue command
+ if (!str[17])
+ return false;
+ humanReadable = (opcode == 'h');
+ if (_ParseCommands(str + 17)) // actual command starts at str[17]
+ {
+ if (!hadAck)
+ SendAck();
+ if (HasSentErrorMessage())
+ SendFailed();
+ else
+ SendOK();
+ }
+ else
+ {
+ SendSysMessage(LANG_NO_CMD);
+ SendFailed();
+ }
+ return true;
+ default:
+ return false;
+ }
+}
+
+void AddonChannelCommandHandler::Send(std::string const& msg)
+{
+ WorldPacket data;
+ ChatHandler::BuildChatPacket(data, CHAT_MSG_WHISPER, LANG_ADDON, GetSession()->GetPlayer(), GetSession()->GetPlayer(), msg);
+ GetSession()->SendPacket(&data);
+}
+
+void AddonChannelCommandHandler::SendAck() // a Command acknowledged, no body
+{
+ ASSERT(echo);
+ char ack[18] = "TrinityCore\ta";
+ memcpy(ack+13, echo, 4);
+ ack[17] = '\0';
+ Send(ack);
+ hadAck = true;
+}
+
+void AddonChannelCommandHandler::SendOK() // o Command OK, no body
+{
+ ASSERT(echo);
+ char ok[18] = "TrinityCore\to";
+ memcpy(ok+13, echo, 4);
+ ok[17] = '\0';
+ Send(ok);
+}
+
+void AddonChannelCommandHandler::SendFailed() // f Command failed, no body
+{
+ ASSERT(echo);
+ char fail[18] = "TrinityCore\tf";
+ memcpy(fail + 13, echo, 4);
+ fail[17] = '\0';
+ Send(fail);
+}
+
+// m Command message, message in body
+void AddonChannelCommandHandler::SendSysMessage(char const* str, bool escapeCharacters)
+{
+ ASSERT(echo);
+ if (!hadAck)
+ SendAck();
+
+ std::string msg = "TrinityCore\tm";
+ msg.append(echo, 4);
+ std::string body(str);
+ if (escapeCharacters)
+ boost::replace_all(body, "|", "||");
+ size_t pos, lastpos;
+ for (lastpos = 0, pos = body.find('\n', lastpos); pos != std::string::npos; lastpos = pos + 1, pos = body.find('\n', lastpos))
+ {
+ std::string line(msg);
+ line.append(body, lastpos, pos - lastpos);
+ Send(line);
+ }
+ msg.append(body, lastpos, pos - lastpos);
+ Send(msg);
+}
diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h
index f2ab3772a0d..8bbcf49c7a1 100644
--- a/src/server/game/Chat/Chat.h
+++ b/src/server/game/Chat/Chat.h
@@ -93,7 +93,8 @@ class TC_GAME_API ChatHandler
return Trinity::StringFormat(GetTrinityString(entry), std::forward<Args>(args)...);
}
- bool ParseCommands(char const* text);
+ bool _ParseCommands(char const* text);
+ virtual bool ParseCommands(char const* text);
static std::vector<ChatCommand> const& getCommandTable();
static void invalidateCommandTable();
@@ -105,6 +106,7 @@ class TC_GAME_API ChatHandler
// function with different implementation for chat/console
virtual bool isAvailable(ChatCommand const& cmd) const;
+ virtual bool IsHumanReadable() const { return true; }
virtual bool HasPermission(uint32 permission) const;
virtual std::string GetNameLink() const;
virtual bool needReportToTarget(Player* chr) const;
@@ -171,6 +173,7 @@ class TC_GAME_API CliHandler : public ChatHandler
bool isAvailable(ChatCommand const& cmd) const override;
bool HasPermission(uint32 /*permission*/) const override { return true; }
void SendSysMessage(const char *str, bool escapeCharacters) override;
+ bool ParseCommands(char const* str) override;
std::string GetNameLink() const override;
bool needReportToTarget(Player* chr) const override;
LocaleConstant GetSessionDbcLocale() const override;
@@ -181,4 +184,24 @@ class TC_GAME_API CliHandler : public ChatHandler
Print* m_print;
};
+class TC_GAME_API AddonChannelCommandHandler : public ChatHandler
+{
+ public:
+ using ChatHandler::ChatHandler;
+ bool ParseCommands(char const* str) override;
+ void SendSysMessage(char const* str, bool escapeCharacters) override;
+ using ChatHandler::SendSysMessage;
+ bool IsHumanReadable() const override { return humanReadable; }
+
+ private:
+ void Send(std::string const& msg);
+ void SendAck();
+ void SendOK();
+ void SendFailed();
+
+ char const* echo = nullptr;
+ bool hadAck = false;
+ bool humanReadable = false;
+};
+
#endif
diff --git a/src/server/game/Chat/ChatLink.cpp b/src/server/game/Chat/ChatLink.cpp
index db07e9e2efd..e7fd0b97703 100644
--- a/src/server/game/Chat/ChatLink.cpp
+++ b/src/server/game/Chat/ChatLink.cpp
@@ -153,7 +153,7 @@ bool ItemChatLink::Initialize(std::istringstream& iss)
return false;
}
}
- else if (id < 0)
+ else
{
_suffix = sItemRandomSuffixStore.LookupEntry(-id);
if (!_suffix)
diff --git a/src/server/game/Combat/ThreatManager.h b/src/server/game/Combat/ThreatManager.h
index a6432d62216..21d975ccea1 100644
--- a/src/server/game/Combat/ThreatManager.h
+++ b/src/server/game/Combat/ThreatManager.h
@@ -20,11 +20,11 @@
#define _THREATMANAGER
#include "Common.h"
+#include "IteratorPair.h"
#include "SharedDefines.h"
#include "LinkedReference/Reference.h"
#include "UnitEvents.h"
#include "ObjectGuid.h"
-#include "Containers.h"
#include <list>
@@ -220,8 +220,8 @@ class TC_GAME_API ThreatManager
{
public:
// -- compatibility layer for combat rewrite (PR #19930)
- Trinity::Containers::IteratorPair<std::list<ThreatReference*>::const_iterator> GetSortedThreatList() const { auto& list = iThreatContainer.getThreatList(); return { list.cbegin(), list.cend() }; }
- Trinity::Containers::IteratorPair<std::list<ThreatReference*>::const_iterator> GetUnsortedThreatList() const { return GetSortedThreatList(); }
+ Trinity::IteratorPair<std::list<ThreatReference*>::const_iterator> GetSortedThreatList() const { auto& list = iThreatContainer.getThreatList(); return { list.cbegin(), list.cend() }; }
+ Trinity::IteratorPair<std::list<ThreatReference*>::const_iterator> GetUnsortedThreatList() const { return GetSortedThreatList(); }
std::list<ThreatReference*> GetModifiableThreatList() const { return iThreatContainer.getThreatList(); }
Unit* SelectVictim() { return getHostilTarget(); }
Unit* GetCurrentVictim() const { if (ThreatReference* ref = getCurrentVictim()) return ref->GetVictim(); else return nullptr; }
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index 146d2cb3bde..5b7e85d6d3e 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -1036,7 +1036,7 @@ void ConditionMgr::LoadConditions(bool isReload)
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 conditions. DB table `conditions` is empty!");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 conditions. DB table `conditions` is empty!");
return;
}
@@ -1677,7 +1677,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const
}
break;
}
- case CONDITION_SOURCE_TYPE_QUEST_ACCEPT:
+ case CONDITION_SOURCE_TYPE_QUEST_AVAILABLE:
if (!sObjectMgr->GetQuestTemplate(cond->SourceEntry))
{
TC_LOG_ERROR("sql.sql", "%s SourceEntry specifies non-existing quest, skipped.", cond->ToString().c_str());
@@ -2011,7 +2011,7 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) const
}
if (cond->ConditionValue3)
{
- if (GameObjectData const* goData = sObjectMgr->GetGOData(cond->ConditionValue3))
+ if (GameObjectData const* goData = sObjectMgr->GetGameObjectData(cond->ConditionValue3))
{
if (cond->ConditionValue2 && goData->id != cond->ConditionValue2)
{
diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h
index ff3f096abae..4f6c98e87d9 100644
--- a/src/server/game/Conditions/ConditionMgr.h
+++ b/src/server/game/Conditions/ConditionMgr.h
@@ -133,7 +133,7 @@ enum ConditionSourceType
CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE = 16,
CONDITION_SOURCE_TYPE_SPELL = 17,
CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT = 18,
- CONDITION_SOURCE_TYPE_QUEST_ACCEPT = 19,
+ CONDITION_SOURCE_TYPE_QUEST_AVAILABLE = 19,
// Condition source type 20 unused
CONDITION_SOURCE_TYPE_VEHICLE_SPELL = 21,
CONDITION_SOURCE_TYPE_SMART_EVENT = 22,
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index f7d3fe325dc..923ed40b93a 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -248,7 +248,7 @@ enum AreaFlags
AREA_FLAG_UNK0 = 0x00000001, // Unknown
AREA_FLAG_UNK1 = 0x00000002, // Razorfen Downs, Naxxramas and Acherus: The Ebon Hold (3.3.5a)
AREA_FLAG_UNK2 = 0x00000004, // Only used for areas on map 571 (development before)
- AREA_FLAG_SLAVE_CAPITAL = 0x00000008, // city and city subsones
+ AREA_FLAG_SLAVE_CAPITAL = 0x00000008, // city and city subzones
AREA_FLAG_UNK3 = 0x00000010, // can't find common meaning
AREA_FLAG_SLAVE_CAPITAL2 = 0x00000020, // slave capital city flag?
AREA_FLAG_ALLOW_DUELS = 0x00000040, // allow to duel here
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp
index e72408205c0..f41e9b4e205 100644
--- a/src/server/game/DataStores/DBCStores.cpp
+++ b/src/server/game/DataStores/DBCStores.cpp
@@ -239,7 +239,7 @@ inline void LoadDBC(uint32& availableDbcLocales, StoreProblemList& errors, DBCSt
localizedName.push_back('/');
localizedName.append(filename);
- if (!storage.LoadStringsFrom(localizedName.c_str()))
+ if (!storage.LoadStringsFrom(localizedName))
availableDbcLocales &= ~(1 << i); // mark as not available for speedup next checks
}
@@ -435,10 +435,10 @@ void LoadDBCStores(const std::string& dataPath)
ASSERT(Utf8toWStr(namesProfanity->Name, wname));
if (namesProfanity->Language != -1)
- NamesProfaneValidators[namesProfanity->Language].emplace_back(wname, Trinity::regex::icase | Trinity::regex::optimize);
+ NamesProfaneValidators[namesProfanity->Language].emplace_back(wname, Trinity::regex::perl | Trinity::regex::icase | Trinity::regex::optimize);
else
for (uint32 i = 0; i < TOTAL_LOCALES; ++i)
- NamesProfaneValidators[i].emplace_back(wname, Trinity::regex::icase | Trinity::regex::optimize);
+ NamesProfaneValidators[i].emplace_back(wname, Trinity::regex::perl | Trinity::regex::icase | Trinity::regex::optimize);
}
for (NamesReservedEntry const* namesReserved : sNamesReservedStore)
@@ -448,10 +448,10 @@ void LoadDBCStores(const std::string& dataPath)
ASSERT(Utf8toWStr(namesReserved->Name, wname));
if (namesReserved->Language != -1)
- NamesReservedValidators[namesReserved->Language].emplace_back(wname, Trinity::regex::icase | Trinity::regex::optimize);
+ NamesReservedValidators[namesReserved->Language].emplace_back(wname, Trinity::regex::perl | Trinity::regex::icase | Trinity::regex::optimize);
else
for (uint32 i = 0; i < TOTAL_LOCALES; ++i)
- NamesReservedValidators[i].emplace_back(wname, Trinity::regex::icase | Trinity::regex::optimize);
+ NamesReservedValidators[i].emplace_back(wname, Trinity::regex::perl | Trinity::regex::icase | Trinity::regex::optimize);
}
for (PvPDifficultyEntry const* entry : sPvPDifficultyStore)
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index 39d30a28c4f..344759a2022 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -129,7 +129,7 @@ void LFGMgr::LoadRewards()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 lfg dungeon rewards. DB table `lfg_dungeon_rewards` is empty!");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 lfg dungeon rewards. DB table `lfg_dungeon_rewards` is empty!");
return;
}
@@ -215,7 +215,7 @@ void LFGMgr::LoadLFGDungeons(bool reload /* = false */)
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 lfg entrance positions. DB table `lfg_dungeon_template` is empty!");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 lfg entrance positions. DB table `lfg_dungeon_template` is empty!");
return;
}
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index b11a5a8018c..27ea877ca08 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -233,14 +233,12 @@ bool ForcedDespawnDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
return true;
}
-Creature::Creature(bool isWorldObject): Unit(isWorldObject), MapObject(),
-m_groupLootTimer(0), lootingGroupLowGUID(0), m_PlayerDamageReq(0),
-m_lootRecipient(), m_lootRecipientGroup(0), _pickpocketLootRestore(0), m_corpseRemoveTime(0), m_respawnTime(0),
-m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_boundaryCheckTime(2500), m_combatPulseTime(0), m_combatPulseDelay(0), m_reactState(REACT_AGGRESSIVE),
-m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false),
-m_AlreadySearchedAssistance(false), m_regenHealth(true), m_cannotReachTarget(false), m_cannotReachTimer(0), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),
-m_originalEntry(0), m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_waypointID(0), m_path_id(0), m_formation(nullptr), m_focusSpell(nullptr), m_focusDelay(0), m_shouldReacquireTarget(false), m_suppressedOrientation(0.0f),
-_lastDamagedTime(0)
+Creature::Creature(bool isWorldObject): Unit(isWorldObject), MapObject(), m_groupLootTimer(0), lootingGroupLowGUID(0), m_PlayerDamageReq(0), m_lootRecipient(), m_lootRecipientGroup(0), _pickpocketLootRestore(0),
+ m_corpseRemoveTime(0), m_respawnTime(0), m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_boundaryCheckTime(2500), m_combatPulseTime(0), m_combatPulseDelay(0), m_reactState(REACT_AGGRESSIVE),
+ m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false), m_cannotReachTarget(false), m_cannotReachTimer(0),
+ m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), _waypointPathId(0), _currentWaypointNodeInfo(0, 0),
+ m_formation(nullptr), m_triggerJustAppeared(true), m_respawnCompatibilityMode(false), m_focusSpell(nullptr), m_focusDelay(0), m_shouldReacquireTarget(false), m_suppressedOrientation(0.0f), _lastDamagedTime(0),
+ _regenerateHealth(true), _regenerateHealthLock(false)
{
m_regenTimer = CREATURE_REGEN_INTERVAL;
m_valuesCount = UNIT_END;
@@ -254,7 +252,6 @@ _lastDamagedTime(0)
m_CombatDistance = 0;//MELEE_RANGE;
ResetLootMode(); // restore default loot mode
- m_TriggerJustRespawned = false;
m_isTempWorldObject = false;
}
@@ -314,6 +311,14 @@ void Creature::DisappearAndDie()
ForcedDespawn(0);
}
+bool Creature::IsReturningHome() const
+{
+ if (GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_ACTIVE) == HOME_MOTION_TYPE)
+ return true;
+
+ return false;
+}
+
void Creature::SearchFormation()
{
if (IsSummon())
@@ -328,48 +333,96 @@ void Creature::SearchFormation()
sFormationMgr->AddCreatureToGroup(frmdata->second->leaderGUID, this);
}
+bool Creature::IsFormationLeader() const
+{
+ if (!m_formation)
+ return false;
+
+ return m_formation->IsLeader(this);
+}
+
+void Creature::SignalFormationMovement(Position const& destination, uint32 id/* = 0*/, uint32 moveType/* = 0*/, bool orientation/* = false*/)
+{
+ if (!m_formation)
+ return;
+
+ if (!m_formation->IsLeader(this))
+ return;
+
+ m_formation->LeaderMoveTo(destination, id, moveType, orientation);
+}
+
+bool Creature::IsFormationLeaderMoveAllowed() const
+{
+ if (!m_formation)
+ return false;
+
+ return m_formation->CanLeaderStartMoving();
+}
+
void Creature::RemoveCorpse(bool setSpawnTime, bool destroyForNearbyPlayers)
{
if (getDeathState() != CORPSE)
return;
- m_corpseRemoveTime = time(nullptr);
- setDeathState(DEAD);
- RemoveAllAuras();
- loot.clear();
- uint32 respawnDelay = m_respawnDelay;
- if (IsAIEnabled)
- AI()->CorpseRemoved(respawnDelay);
+ if (m_respawnCompatibilityMode)
+ {
+ m_corpseRemoveTime = time(nullptr);
+ setDeathState(DEAD);
+ RemoveAllAuras();
+ loot.clear();
+ uint32 respawnDelay = m_respawnDelay;
+ if (IsAIEnabled)
+ AI()->CorpseRemoved(respawnDelay);
- if (destroyForNearbyPlayers)
- DestroyForNearbyPlayers();
+ if (destroyForNearbyPlayers)
+ DestroyForNearbyPlayers();
- // Should get removed later, just keep "compatibility" with scripts
- if (setSpawnTime)
- m_respawnTime = std::max<time_t>(time(nullptr) + respawnDelay, m_respawnTime);
+ // Should get removed later, just keep "compatibility" with scripts
+ if (setSpawnTime)
+ m_respawnTime = std::max<time_t>(time(nullptr) + respawnDelay, m_respawnTime);
- // if corpse was removed during falling, the falling will continue and override relocation to respawn position
- if (IsFalling())
- StopMoving();
+ // if corpse was removed during falling, the falling will continue and override relocation to respawn position
+ if (IsFalling())
+ StopMoving();
- float x, y, z, o;
- GetRespawnPosition(x, y, z, &o);
+ float x, y, z, o;
+ GetRespawnPosition(x, y, z, &o);
- // We were spawned on transport, calculate real position
- if (IsSpawnedOnTransport())
- {
- Position& pos = m_movementInfo.transport.pos;
- pos.m_positionX = x;
- pos.m_positionY = y;
- pos.m_positionZ = z;
- pos.SetOrientation(o);
+ // We were spawned on transport, calculate real position
+ if (IsSpawnedOnTransport())
+ {
+ Position& pos = m_movementInfo.transport.pos;
+ pos.m_positionX = x;
+ pos.m_positionY = y;
+ pos.m_positionZ = z;
+ pos.SetOrientation(o);
+
+ if (TransportBase* transport = GetDirectTransport())
+ transport->CalculatePassengerPosition(x, y, z, &o);
+ }
- if (TransportBase* transport = GetDirectTransport())
- transport->CalculatePassengerPosition(x, y, z, &o);
+ SetHomePosition(x, y, z, o);
+ GetMap()->CreatureRelocation(this, x, y, z, o);
}
+ else
+ {
+ // In case this is called directly and normal respawn timer not set
+ // Since this timer will be longer than the already present time it
+ // will be ignored if the correct place added a respawn timer
+ if (setSpawnTime)
+ {
+ uint32 respawnDelay = m_respawnDelay;
+ m_respawnTime = std::max<time_t>(time(NULL) + respawnDelay, m_respawnTime);
+
+ SaveRespawnTime(0, false);
+ }
- SetHomePosition(x, y, z, o);
- GetMap()->CreatureRelocation(this, x, y, z, o);
+ if (TempSummon* summon = ToTempSummon())
+ summon->UnSummon();
+ else
+ AddObjectToRemoveList();
+ }
}
/**
@@ -478,7 +531,7 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/,
CreatureTemplate const* cInfo = GetCreatureTemplate();
- m_regenHealth = cInfo->RegenHealth;
+ _regenerateHealth = cInfo->RegenHealth;
// creatures always have melee weapon ready if any unless specified otherwise
if (!GetCreatureAddon())
@@ -561,12 +614,12 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/,
void Creature::Update(uint32 diff)
{
- if (IsAIEnabled && m_TriggerJustRespawned)
+ if (IsAIEnabled && m_triggerJustAppeared && m_deathState == ALIVE)
{
- m_TriggerJustRespawned = false;
- AI()->JustRespawned();
- if (m_vehicleKit)
+ if (m_respawnCompatibilityMode && m_vehicleKit)
m_vehicleKit->Reset();
+ m_triggerJustAppeared = false;
+ AI()->JustAppeared();
}
UpdateMovementFlags();
@@ -579,30 +632,34 @@ void Creature::Update(uint32 diff)
break;
case JUST_DIED:
// Must not be called, see Creature::setDeathState JUST_DIED -> CORPSE promoting.
- TC_LOG_ERROR("entities.unit", "Creature (GUID: %u Entry: %u) in wrong state: JUST_DEAD (1)", GetGUID().GetCounter(), GetEntry());
+ TC_LOG_ERROR("entities.unit", "Creature (GUID: %u Entry: %u) in wrong state: JUST_DIED (1)", GetGUID().GetCounter(), GetEntry());
break;
case DEAD:
{
time_t now = time(nullptr);
if (m_respawnTime <= now)
{
+
// First check if there are any scripts that object to us respawning
- if (!sScriptMgr->CanSpawn(GetSpawnId(), GetEntry(), GetCreatureTemplate(), GetCreatureData(), GetMap()))
- break; // Will be rechecked on next Update call
+ if (!sScriptMgr->CanSpawn(GetSpawnId(), GetEntry(), GetCreatureData(), GetMap()))
+ {
+ m_respawnTime = now + urand(4,7);
+ break; // Will be rechecked on next Update call after delay expires
+ }
ObjectGuid dbtableHighGuid(HighGuid::Unit, GetEntry(), m_spawnId);
- time_t linkedRespawntime = GetMap()->GetLinkedRespawnTime(dbtableHighGuid);
- if (!linkedRespawntime) // Can respawn
+ time_t linkedRespawnTime = GetMap()->GetLinkedRespawnTime(dbtableHighGuid);
+ if (!linkedRespawnTime) // Can respawn
Respawn();
else // the master is dead
{
ObjectGuid targetGuid = sObjectMgr->GetLinkedRespawnGuid(dbtableHighGuid);
- if (targetGuid == dbtableHighGuid) // if linking self, never respawn (check delayed to next day)
- SetRespawnTime(DAY);
+ if (targetGuid == dbtableHighGuid) // if linking self, never respawn
+ SetRespawnTime(WEEK);
else
{
// else copy time from master and add a little
- time_t baseRespawnTime = std::max(linkedRespawntime, now);
+ time_t baseRespawnTime = std::max(linkedRespawnTime, now);
time_t const offset = urand(5, MINUTE);
// linked guid can be a boss, uses std::numeric_limits<time_t>::max to never respawn in that instance
@@ -742,7 +799,7 @@ void Creature::Update(uint32 diff)
if (m_regenTimer == 0)
{
- bool bInCombat = IsInCombat() && (!GetVictim() || // if IsInCombat() is true and this has no victim
+ bool bInCombat = IsInCombat() && (!GetVictim() || // if IsInCombat() is true and this has no victim
!EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself() || // or the victim/owner/charmer is not a player
!EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()->IsGameMaster()); // or the victim/owner/charmer is not a GameMaster
@@ -830,7 +887,7 @@ void Creature::Regenerate(Powers power)
void Creature::RegenerateHealth()
{
- if (!isRegeneratingHealth())
+ if (!CanRegenerateHealth())
return;
uint32 curValue = GetHealth();
@@ -947,12 +1004,16 @@ void Creature::Motion_Initialize()
GetMotionMaster()->Initialize();
}
-bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, uint32 entry, float x, float y, float z, float ang, CreatureData const* data /*= nullptr*/, uint32 vehId /*= 0*/)
+bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, uint32 entry, Position const& pos, CreatureData const* data /*= nullptr*/, uint32 vehId /*= 0*/, bool dynamic)
{
ASSERT(map);
SetMap(map);
SetPhaseMask(phaseMask, false);
+ // Set if this creature can handle dynamic spawns
+ if (!dynamic)
+ SetRespawnCompatibilityMode();
+
CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(entry);
if (!cinfo)
{
@@ -962,15 +1023,16 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, u
//! Relocate before CreateFromProto, to initialize coords and allow
//! returning correct zone id for selecting OutdoorPvP/Battlefield script
- Relocate(x, y, z, ang);
+ Relocate(pos);
// Check if the position is valid before calling CreateFromProto(), otherwise we might add Auras to Creatures at
// invalid position, triggering a crash about Auras not removed in the destructor
if (!IsPositionValid())
{
- TC_LOG_ERROR("entities.unit", "Creature::Create(): given coordinates for creature (guidlow %d, entry %d) are not valid (X: %f, Y: %f, Z: %f, O: %f)", guidlow, entry, x, y, z, ang);
+ TC_LOG_ERROR("entities.unit", "Creature::Create(): given coordinates for creature (guidlow %d, entry %d) are not valid (X: %f, Y: %f, Z: %f, O: %f)", guidlow, entry, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation());
return false;
}
+ UpdatePositionData();
// Allow players to see those units while dead, do it here (mayby altered by addon auras)
if (cinfo->type_flags & CREATURE_TYPE_FLAG_GHOST_VISIBLE)
@@ -1004,10 +1066,8 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, u
//! Need to be called after LoadCreaturesAddon - MOVEMENTFLAG_HOVER is set there
if (HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
{
- z += GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
-
//! Relocate again with updated Z coord
- Relocate(x, y, z, ang);
+ m_positionZ += GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
}
LastUsedScriptID = GetScriptId();
@@ -1187,27 +1247,17 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
dynamicflags = 0;
}
- // data->guid = guid must not be updated at save
+ if (!data.spawnId)
+ data.spawnId = m_spawnId;
+ ASSERT(data.spawnId == m_spawnId);
data.id = GetEntry();
- data.mapid = mapid;
data.phaseMask = phaseMask;
data.displayid = displayId;
data.equipmentId = GetCurrentEquipmentId();
if (!GetTransport())
- {
- data.posX = GetPositionX();
- data.posY = GetPositionY();
- data.posZ = GetPositionZMinusOffset();
- data.orientation = GetOrientation();
- }
+ data.spawnPoint.WorldRelocate(this);
else
- {
- data.posX = GetTransOffsetX();
- data.posY = GetTransOffsetY();
- data.posZ = GetTransOffsetZ();
- data.orientation = GetTransOffsetO();
- }
-
+ data.spawnPoint.WorldRelocate(mapid, GetTransOffsetX(), GetTransOffsetY(), GetTransOffsetZ(), GetTransOffsetO());
data.spawntimesecs = m_respawnDelay;
// prevent add data integrity problems
data.spawndist = GetDefaultMovementType() == IDLE_MOTION_TYPE ? 0.0f : m_respawnradius;
@@ -1221,6 +1271,8 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
data.npcflag = npcflag;
data.unit_flags = unit_flags;
data.dynamicflags = dynamicflags;
+ if (!data.spawnGroupData)
+ data.spawnGroupData = sObjectMgr->GetDefaultSpawnGroup();
// update in DB
SQLTransaction trans = WorldDatabase.BeginTransaction();
@@ -1425,7 +1477,7 @@ bool Creature::CreateFromProto(ObjectGuid::LowType guidlow, uint32 entry, Creatu
return true;
}
-bool Creature::LoadCreatureFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap, bool allowDuplicate)
+bool Creature::LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap, bool allowDuplicate)
{
if (!allowDuplicate)
{
@@ -1466,31 +1518,41 @@ bool Creature::LoadCreatureFromDB(ObjectGuid::LowType spawnId, Map* map, bool ad
}
m_spawnId = spawnId;
+
+ m_respawnCompatibilityMode = ((data->spawnGroupData->flags & SPAWNGROUP_FLAG_COMPATIBILITY_MODE) != 0);
m_creatureData = data;
m_respawnradius = data->spawndist;
m_respawnDelay = data->spawntimesecs;
- if (!Create(map->GenerateLowGuid<HighGuid::Unit>(), map, data->phaseMask, data->id, data->posX, data->posY, data->posZ, data->orientation, data))
+
+ // Is the creature script objecting to us spawning? If yes, delay by a little bit (then re-check in ::Update)
+ if (!m_respawnCompatibilityMode && !m_respawnTime && !sScriptMgr->CanSpawn(spawnId, data->id, data, map))
+ {
+ SaveRespawnTime(urand(4,7));
+ return false;
+ }
+
+ if (!Create(map->GenerateLowGuid<HighGuid::Unit>(), map, data->phaseMask, data->id, data->spawnPoint, data, 0U , !m_respawnCompatibilityMode))
return false;
//We should set first home position, because then AI calls home movement
- SetHomePosition(data->posX, data->posY, data->posZ, data->orientation);
+ SetHomePosition(data->spawnPoint);
m_deathState = ALIVE;
m_respawnTime = GetMap()->GetCreatureRespawnTime(m_spawnId);
- // Is the creature script objecting to us spawning? If yes, delay by one second (then re-check in ::Update)
- if (!m_respawnTime && !sScriptMgr->CanSpawn(spawnId, GetEntry(), GetCreatureTemplate(), GetCreatureData(), map))
- m_respawnTime = time(nullptr)+1;
+ // Is the creature script objecting to us spawning? If yes, delay by a little bit (then re-check in ::Update)
+ if (m_respawnCompatibilityMode && !m_respawnTime && !sScriptMgr->CanSpawn(spawnId, GetEntry(), GetCreatureData(), map))
+ m_respawnTime = time(nullptr)+urand(4,7);
if (m_respawnTime) // respawn on Update
{
m_deathState = DEAD;
if (CanFly())
{
- float tz = map->GetHeight(GetPhaseMask(), data->posX, data->posY, data->posZ, true, MAX_FALL_DISTANCE);
- if (data->posZ - tz > 0.1f && Trinity::IsValidMapCoord(tz))
- Relocate(data->posX, data->posY, tz);
+ float tz = map->GetHeight(GetPhaseMask(), data->spawnPoint, true, MAX_FALL_DISTANCE);
+ if (data->spawnPoint.GetPositionZ() - tz > 0.1f && Trinity::IsValidMapCoord(tz))
+ Relocate(data->spawnPoint.GetPositionX(), data->spawnPoint.GetPositionY(), tz);
}
}
@@ -1535,8 +1597,11 @@ void Creature::LoadEquipment(int8 id, bool force /*= true*/)
void Creature::SetSpawnHealth()
{
+ if (_regenerateHealthLock)
+ return;
+
uint32 curhealth;
- if (m_creatureData && !m_regenHealth)
+ if (m_creatureData && !_regenerateHealth)
{
curhealth = m_creatureData->curhealth;
if (curhealth)
@@ -1586,15 +1651,24 @@ void Creature::DeleteFromDB()
return;
}
- GetMap()->RemoveCreatureRespawnTime(m_spawnId);
+ // remove any scheduled respawns
+ GetMap()->RemoveRespawnTime(SPAWN_TYPE_CREATURE, m_spawnId);
+
+ // delete data from memory
sObjectMgr->DeleteCreatureData(m_spawnId);
+ // delete data and all its associations from DB
SQLTransaction trans = WorldDatabase.BeginTransaction();
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE);
stmt->setUInt32(0, m_spawnId);
trans->Append(stmt);
+ stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_SPAWNGROUP_MEMBER);
+ stmt->setUInt8(0, uint8(SPAWN_TYPE_CREATURE));
+ stmt->setUInt32(1, m_spawnId);
+ trans->Append(stmt);
+
stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE_ADDON);
stmt->setUInt32(0, m_spawnId);
trans->Append(stmt);
@@ -1608,6 +1682,11 @@ void Creature::DeleteFromDB()
trans->Append(stmt);
WorldDatabase.CommitTransaction(trans);
+
+ // then delete any active instances of the creature
+ auto const& spawnMap = GetMap()->GetCreatureBySpawnIdStore();
+ for (auto it = spawnMap.find(m_spawnId); it != spawnMap.end(); it = spawnMap.find(m_spawnId))
+ it->second->AddObjectToRemoveList();
}
bool Creature::IsInvisibleDueToDespawn() const
@@ -1734,14 +1813,31 @@ void Creature::setDeathState(DeathState s)
if (s == JUST_DIED)
{
m_corpseRemoveTime = time(nullptr) + m_corpseDelay;
- if (IsDungeonBoss() && !m_respawnDelay)
- m_respawnTime = std::numeric_limits<time_t>::max(); // never respawn in this instance
+
+ uint32 respawnDelay = m_respawnDelay;
+ if (uint32 scalingMode = sWorld->getIntConfig(CONFIG_RESPAWN_DYNAMICMODE))
+ GetMap()->ApplyDynamicModeRespawnScaling(this, m_spawnId, respawnDelay, scalingMode);
+ // @todo remove the boss respawn time hack in a dynspawn follow-up once we have creature groups in instances
+ if (m_respawnCompatibilityMode)
+ {
+ if (IsDungeonBoss() && !m_respawnDelay)
+ m_respawnTime = std::numeric_limits<time_t>::max(); // never respawn in this instance
+ else
+ m_respawnTime = time(nullptr) + respawnDelay + m_corpseDelay;
+ }
else
- m_respawnTime = time(nullptr) + m_respawnDelay + m_corpseDelay;
+ {
+ if (IsDungeonBoss() && !m_respawnDelay)
+ m_respawnTime = std::numeric_limits<time_t>::max(); // never respawn in this instance
+ else
+ m_respawnTime = time(nullptr) + respawnDelay;
+ }
// always save boss respawn time at death to prevent crash cheating
if (sWorld->getBoolConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY) || isWorldBoss())
SaveRespawnTime();
+ else if (!m_respawnCompatibilityMode)
+ SaveRespawnTime(0, false);
ReleaseFocus(nullptr, false); // remove spellcast focus
DoNotReacquireTarget(); // cancel delayed re-target
@@ -1809,8 +1905,6 @@ void Creature::setDeathState(DeathState s)
void Creature::Respawn(bool force)
{
- DestroyForNearbyPlayers();
-
if (force)
{
if (IsAlive())
@@ -1819,51 +1913,59 @@ void Creature::Respawn(bool force)
setDeathState(CORPSE);
}
- RemoveCorpse(false, false);
-
- if (getDeathState() == DEAD)
+ if (m_respawnCompatibilityMode)
{
- if (m_spawnId)
- GetMap()->RemoveCreatureRespawnTime(m_spawnId);
+ DestroyForNearbyPlayers();
+ RemoveCorpse(false, false);
- TC_LOG_DEBUG("entities.unit", "Respawning creature %s (%s)",
- GetName().c_str(), GetGUID().ToString().c_str());
- m_respawnTime = 0;
- ResetPickPocketRefillTimer();
- loot.clear();
+ if (getDeathState() == DEAD)
+ {
+ if (m_spawnId)
+ GetMap()->RemoveRespawnTime(SPAWN_TYPE_CREATURE, m_spawnId);
- if (m_originalEntry != GetEntry())
- UpdateEntry(m_originalEntry);
+ TC_LOG_DEBUG("entities.unit", "Respawning creature %s (%s)", GetName().c_str(), GetGUID().ToString().c_str());
+ m_respawnTime = 0;
+ ResetPickPocketRefillTimer();
+ loot.clear();
- SelectLevel();
+ if (m_originalEntry != GetEntry())
+ UpdateEntry(m_originalEntry);
- setDeathState(JUST_RESPAWNED);
+ SelectLevel();
- uint32 displayID = GetNativeDisplayId();
- if (sObjectMgr->GetCreatureModelRandomGender(&displayID))
- {
- SetDisplayId(displayID);
- SetNativeDisplayId(displayID);
- }
+ setDeathState(JUST_RESPAWNED);
- GetMotionMaster()->InitDefault();
- //Re-initialize reactstate that could be altered by movementgenerators
- InitializeReactState();
+ uint32 displayID = GetNativeDisplayId();
+ if (sObjectMgr->GetCreatureModelRandomGender(&displayID))
+ {
+ SetDisplayId(displayID);
+ SetNativeDisplayId(displayID);
+ }
- //Call AI respawn virtual function
- if (IsAIEnabled)
- {
- //reset the AI to be sure no dirty or uninitialized values will be used till next tick
- AI()->Reset();
- m_TriggerJustRespawned = true;//delay event to next tick so all creatures are created on the map before processing
- }
+ GetMotionMaster()->InitDefault();
+ //Re-initialize reactstate that could be altered by movementgenerators
+ InitializeReactState();
- uint32 poolid = GetSpawnId() ? sPoolMgr->IsPartOfAPool<Creature>(GetSpawnId()) : 0;
- if (poolid)
- sPoolMgr->UpdatePool<Creature>(poolid, GetSpawnId());
+ if (IsAIEnabled) // reset the AI to be sure no dirty or uninitialized values will be used till next tick
+ AI()->Reset();
+
+ m_triggerJustAppeared = true;
+
+ uint32 poolid = GetSpawnId() ? sPoolMgr->IsPartOfAPool<Creature>(GetSpawnId()) : 0;
+ if (poolid)
+ sPoolMgr->UpdatePool<Creature>(poolid, GetSpawnId());
+ }
+ UpdateObjectVisibility();
+ }
+ else
+ {
+ if (m_spawnId)
+ GetMap()->RemoveRespawnTime(SPAWN_TYPE_CREATURE, m_spawnId, true);
}
- UpdateObjectVisibility();
+ TC_LOG_DEBUG("entities.unit", "Respawning creature %s (%s)",
+ GetName().c_str(), GetGUID().ToString().c_str());
+
}
void Creature::ForcedDespawn(uint32 timeMSToDespawn, Seconds const& forceRespawnTimer)
@@ -1874,30 +1976,48 @@ void Creature::ForcedDespawn(uint32 timeMSToDespawn, Seconds const& forceRespawn
return;
}
- uint32 corpseDelay = GetCorpseDelay();
- uint32 respawnDelay = GetRespawnDelay();
+ if (m_respawnCompatibilityMode)
+ {
+ uint32 corpseDelay = GetCorpseDelay();
+ uint32 respawnDelay = GetRespawnDelay();
+
+ // do it before killing creature
+ DestroyForNearbyPlayers();
- // do it before killing creature
- DestroyForNearbyPlayers();
+ bool overrideRespawnTime = false;
+ if (IsAlive())
+ {
+ if (forceRespawnTimer > Seconds::zero())
+ {
+ SetCorpseDelay(0);
+ SetRespawnDelay(forceRespawnTimer.count());
+ overrideRespawnTime = true;
+ }
- bool overrideRespawnTime = true;
- if (IsAlive())
+ setDeathState(JUST_DIED);
+ }
+
+ // Skip corpse decay time
+ RemoveCorpse(!overrideRespawnTime, false);
+
+ SetCorpseDelay(corpseDelay);
+ SetRespawnDelay(respawnDelay);
+ }
+ else
{
if (forceRespawnTimer > Seconds::zero())
+ SaveRespawnTime(forceRespawnTimer.count());
+ else
{
- SetCorpseDelay(0);
- SetRespawnDelay(forceRespawnTimer.count());
- overrideRespawnTime = false;
+ uint32 respawnDelay = m_respawnDelay;
+ if (uint32 scalingMode = sWorld->getIntConfig(CONFIG_RESPAWN_DYNAMICMODE))
+ GetMap()->ApplyDynamicModeRespawnScaling(this, m_spawnId, respawnDelay, scalingMode);
+ m_respawnTime = time(NULL) + respawnDelay;
+ SaveRespawnTime();
}
- setDeathState(JUST_DIED);
+ AddObjectToRemoveList();
}
-
- // Skip corpse decay time
- RemoveCorpse(overrideRespawnTime, false);
-
- SetCorpseDelay(corpseDelay);
- SetRespawnDelay(respawnDelay);
}
void Creature::DespawnOrUnsummon(uint32 msTimeToDespawn /*= 0*/, Seconds const& forceRespawnTimer /*= 0*/)
@@ -2156,9 +2276,6 @@ void Creature::CallForHelp(float radius)
bool Creature::CanAssistTo(Unit const* u, Unit const* enemy, bool checkfaction /*= true*/) const
{
- if (IsInEvadeMode())
- return false;
-
// is it true?
if (!HasReactState(REACT_AGGRESSIVE))
return false;
@@ -2244,12 +2361,19 @@ bool Creature::_IsTargetAcceptable(Unit const* target) const
return false;
}
-void Creature::SaveRespawnTime()
+void Creature::SaveRespawnTime(uint32 forceDelay, bool savetodb)
{
if (IsSummon() || !m_spawnId || (m_creatureData && !m_creatureData->dbData))
return;
- GetMap()->SaveCreatureRespawnTime(m_spawnId, m_respawnTime);
+ if (m_respawnCompatibilityMode)
+ {
+ GetMap()->SaveRespawnTimeDB(SPAWN_TYPE_CREATURE, m_spawnId, m_respawnTime);
+ return;
+ }
+
+ time_t thisRespawnTime = forceDelay ? time(NULL) + forceDelay : m_respawnTime;
+ GetMap()->SaveRespawnTime(SPAWN_TYPE_CREATURE, m_spawnId, GetEntry(), thisRespawnTime, GetMap()->GetZoneId(GetHomePosition()), Trinity::ComputeGridCoord(GetHomePosition().GetPositionX(), GetHomePosition().GetPositionY()).GetId(), savetodb && m_creatureData && m_creatureData->dbData);
}
// this should not be called by petAI or
@@ -2365,9 +2489,9 @@ bool Creature::LoadCreaturesAddon()
if (cainfo->emote != 0)
SetUInt32Value(UNIT_NPC_EMOTESTATE, cainfo->emote);
- //Load Path
+ // Load Path
if (cainfo->path_id != 0)
- m_path_id = cainfo->path_id;
+ _waypointPathId = cainfo->path_id;
if (!cainfo->auras.empty())
{
@@ -2461,33 +2585,26 @@ time_t Creature::GetRespawnTimeEx() const
void Creature::GetRespawnPosition(float &x, float &y, float &z, float* ori, float* dist) const
{
- if (m_spawnId)
+ if (m_creatureData)
{
- // for npcs on transport, this will return transport offset
- if (CreatureData const* data = sObjectMgr->GetCreatureData(GetSpawnId()))
- {
- x = data->posX;
- y = data->posY;
- z = data->posZ;
- if (ori)
- *ori = data->orientation;
- if (dist)
- *dist = data->spawndist;
+ if (ori)
+ m_creatureData->spawnPoint.GetPosition(x, y, z, *ori);
+ else
+ m_creatureData->spawnPoint.GetPosition(x, y, z);
- return;
- }
+ if (dist)
+ *dist = m_creatureData->spawndist;
+ }
+ else
+ {
+ Position const& homePos = GetHomePosition();
+ if (ori)
+ homePos.GetPosition(x, y, z, *ori);
+ else
+ homePos.GetPosition(x, y, z);
+ if (dist)
+ *dist = 0;
}
-
- // changed this from current position to home position, fixes world summons with infinite duration (wg npcs for example)
- Position homePos = GetHomePosition();
- x = homePos.GetPositionX();
- y = homePos.GetPositionY();
- z = homePos.GetPositionZ();
- if (ori)
- *ori = homePos.GetOrientation();
-
- if (dist)
- *dist = 0;
}
void Creature::AllLootRemovedFromCorpse()
@@ -2538,7 +2655,7 @@ std::string Creature::GetScriptName() const
uint32 Creature::GetScriptId() const
{
if (CreatureData const* creatureData = GetCreatureData())
- if (uint32 scriptId = creatureData->ScriptId)
+ if (uint32 scriptId = creatureData->scriptId)
return scriptId;
return sObjectMgr->GetCreatureTemplate(GetEntry())->ScriptID;
@@ -3081,3 +3198,11 @@ bool Creature::CanGiveExperience() const
&& !IsTotem()
&& !(GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL);
}
+
+bool Creature::IsEscortNPC(bool onlyIfActive)
+{
+ if (!IsAIEnabled)
+ return false;
+
+ return AI()->IsEscortNPC(onlyIfActive);
+}
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index cc12efbd7eb..4a7c3362f30 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -35,6 +35,7 @@ class Quest;
class Player;
class SpellInfo;
class WorldSession;
+
enum MovementGeneratorType : uint8;
struct VendorItemCount
@@ -72,7 +73,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
void DisappearAndDie();
- bool Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, uint32 entry, float x, float y, float z, float ang, CreatureData const* data = nullptr, uint32 vehId = 0);
+ bool Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, uint32 entry, Position const& pos, CreatureData const* data = nullptr, uint32 vehId = 0, bool dynamic = false);
bool LoadCreaturesAddon();
void SelectLevel();
void UpdateLevelDependantStats();
@@ -83,7 +84,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
void Update(uint32 time) override; // overwrited Unit::Update
void GetRespawnPosition(float &x, float &y, float &z, float* ori = nullptr, float* dist = nullptr) const;
- bool IsSpawnedOnTransport() const { return m_creatureData && m_creatureData->mapid != GetMapId(); }
+ bool IsSpawnedOnTransport() const { return m_creatureData && m_creatureData->spawnPoint.GetMapId() != GetMapId(); }
void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; }
uint32 GetCorpseDelay() const { return m_corpseDelay; }
@@ -176,8 +177,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
void setDeathState(DeathState s) override; // override virtual Unit::setDeathState
- bool LoadFromDB(ObjectGuid::LowType spawnId, Map* map) { return LoadCreatureFromDB(spawnId, map, false); }
- bool LoadCreatureFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap = true, bool allowDuplicate = false);
+ bool LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap, bool allowDuplicate);
void SaveToDB();
// overriden in Pet
virtual void SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask);
@@ -239,7 +239,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
time_t GetRespawnTimeEx() const;
void SetRespawnTime(uint32 respawn) { m_respawnTime = respawn ? time(nullptr) + respawn : 0; }
void Respawn(bool force = false);
- void SaveRespawnTime() override;
+ void SaveRespawnTime(uint32 forceDelay = 0, bool savetodb = true) override;
uint32 GetRespawnDelay() const { return m_respawnDelay; }
void SetRespawnDelay(uint32 delay) { m_respawnDelay = delay; }
@@ -266,8 +266,8 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
bool hasQuest(uint32 quest_id) const override;
bool hasInvolvedQuest(uint32 quest_id) const override;
- bool isRegeneratingHealth() { return m_regenHealth; }
- void setRegeneratingHealth(bool regenHealth) { m_regenHealth = regenHealth; }
+ bool CanRegenerateHealth() { return !_regenerateHealthLock && _regenerateHealth; }
+ void SetRegenerateHealth(bool value) { _regenerateHealthLock = !value; }
virtual uint8 GetPetAutoSpellSize() const { return MAX_SPELL_CHARM; }
virtual uint32 GetPetAutoSpellOnPos(uint8 pos) const;
float GetPetChaseDistance() const;
@@ -291,15 +291,21 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
void GetTransportHomePosition(float& x, float& y, float& z, float& ori) const { m_transportHomePosition.GetPosition(x, y, z, ori); }
Position const& GetTransportHomePosition() const { return m_transportHomePosition; }
- uint32 GetWaypointPath() const { return m_path_id; }
- void LoadPath(uint32 pathid) { m_path_id = pathid; }
+ uint32 GetWaypointPath() const { return _waypointPathId; }
+ void LoadPath(uint32 pathid) { _waypointPathId = pathid; }
+
+ // nodeId, pathId
+ std::pair<uint32, uint32> GetCurrentWaypointInfo() const { return _currentWaypointNodeInfo; }
+ void UpdateCurrentWaypointInfo(uint32 nodeId, uint32 pathId) { _currentWaypointNodeInfo = { nodeId, pathId }; }
- uint32 GetCurrentWaypointID() const { return m_waypointID; }
- void UpdateWaypointID(uint32 wpID) { m_waypointID = wpID; }
+ bool IsReturningHome() const;
void SearchFormation();
CreatureGroup* GetFormation() { return m_formation; }
void SetFormation(CreatureGroup* formation) { m_formation = formation; }
+ bool IsFormationLeader() const;
+ void SignalFormationMovement(Position const& destination, uint32 id = 0, uint32 moveType = 0, bool orientation = false);
+ bool IsFormationLeaderMoveAllowed() const;
Unit* SelectVictim();
@@ -313,6 +319,10 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
uint32 GetOriginalEntry() const { return m_originalEntry; }
void SetOriginalEntry(uint32 entry) { m_originalEntry = entry; }
+ // There's many places not ready for dynamic spawns. This allows them to live on for now.
+ void SetRespawnCompatibilityMode(bool mode = true) { m_respawnCompatibilityMode = mode; }
+ bool GetRespawnCompatibilityMode() { return m_respawnCompatibilityMode; }
+
static float _GetDamageMod(int32 Rank);
float m_SightDistance, m_CombatDistance;
@@ -336,6 +346,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
CreatureTextRepeatIds GetTextRepeatGroup(uint8 textGroup);
void SetTextRepeatId(uint8 textGroup, uint8 id);
void ClearTextRepeatGroup(uint8 textGroup);
+ bool IsEscortNPC(bool onlyIfActive = true);
bool CanGiveExperience() const;
@@ -372,7 +383,6 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
bool m_AlreadyCallAssistance;
bool m_AlreadySearchedAssistance;
- bool m_regenHealth;
bool m_cannotReachTarget;
uint32 m_cannotReachTimer;
bool m_AI_locked;
@@ -397,13 +407,14 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
void ForcedDespawn(uint32 timeMSToDespawn = 0, Seconds const& forceRespawnTimer = Seconds(0));
bool CheckNoGrayAggroConfig(uint32 playerLevel, uint32 creatureLevel) const; // No aggro from gray creatures
- //WaypointMovementGenerator vars
- uint32 m_waypointID;
- uint32 m_path_id;
+ // Waypoint path
+ uint32 _waypointPathId;
+ std::pair<uint32/*nodeId*/, uint32/*pathId*/> _currentWaypointNodeInfo;
//Formation var
CreatureGroup* m_formation;
- bool m_TriggerJustRespawned;
+ bool m_triggerJustAppeared;
+ bool m_respawnCompatibilityMode;
/* Spell focus system */
Spell const* m_focusSpell; // Locks the target during spell cast for proper facing
@@ -414,6 +425,10 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
time_t _lastDamagedTime; // Part of Evade mechanics
CreatureTextRepeatGroup m_textRepeat;
+
+ // Regenerate health
+ bool _regenerateHealth; // Set on creation
+ bool _regenerateHealthLock; // Dynamically set
};
class TC_GAME_API AssistDelayEvent : public BasicEvent
diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h
index 754963f9812..de169c97136 100644
--- a/src/server/game/Entities/Creature/CreatureData.h
+++ b/src/server/game/Entities/Creature/CreatureData.h
@@ -20,6 +20,7 @@
#include "DBCEnums.h"
#include "SharedDefines.h"
+#include "SpawnData.h"
#include "UnitDefines.h"
#include "WorldPacket.h"
#include <string>
@@ -235,33 +236,19 @@ struct EquipmentInfo
};
// from `creature` table
-struct CreatureData
+struct CreatureData : public SpawnData
{
- CreatureData() : id(0), mapid(0), phaseMask(0), displayid(0), equipmentId(0),
- posX(0.0f), posY(0.0f), posZ(0.0f), orientation(0.0f), spawntimesecs(0),
- spawndist(0.0f), currentwaypoint(0), curhealth(0), curmana(0), movementType(0),
- spawnMask(0), npcflag(0), unit_flags(0), dynamicflags(0), ScriptId(0), dbData(true) { }
- uint32 id; // entry in creature_template
- uint16 mapid;
- uint32 phaseMask;
- uint32 displayid;
- int8 equipmentId;
- float posX;
- float posY;
- float posZ;
- float orientation;
- uint32 spawntimesecs;
- float spawndist;
- uint32 currentwaypoint;
- uint32 curhealth;
- uint32 curmana;
- uint8 movementType;
- uint8 spawnMask;
- uint32 npcflag;
- uint32 unit_flags; // enum UnitFlags mask values
- uint32 dynamicflags;
- uint32 ScriptId;
- bool dbData;
+ CreatureData() : SpawnData(SPAWN_TYPE_CREATURE) { }
+ uint32 displayid = 0;
+ int8 equipmentId = 0;
+ float spawndist = 0.0f;
+ uint32 currentwaypoint = 0;
+ uint32 curhealth = 0;
+ uint32 curmana = 0;
+ uint8 movementType = 0;
+ uint32 npcflag = 0;
+ uint32 unit_flags = 0;
+ uint32 dynamicflags = 0;
};
struct CreatureModelInfo
diff --git a/src/server/game/Entities/Creature/CreatureGroups.cpp b/src/server/game/Entities/Creature/CreatureGroups.cpp
index 3984a81cf71..4297a745ccc 100644
--- a/src/server/game/Entities/Creature/CreatureGroups.cpp
+++ b/src/server/game/Entities/Creature/CreatureGroups.cpp
@@ -93,7 +93,7 @@ void FormationMgr::LoadCreatureFormations()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 creatures in formations. DB table `creature_formations` is empty!");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 creatures in formations. DB table `creature_formations` is empty!");
return;
}
@@ -236,7 +236,7 @@ void CreatureGroup::LeaderMoveTo(Position const& destination, uint32 id /*= 0*/,
continue;
if (itr->second->point_1)
- if (m_leader->GetCurrentWaypointID() == itr->second->point_1 - 1 || m_leader->GetCurrentWaypointID() == itr->second->point_2 - 1)
+ if (m_leader->GetCurrentWaypointInfo().first == itr->second->point_1 || m_leader->GetCurrentWaypointInfo().first == itr->second->point_2)
itr->second->follow_angle = float(M_PI) * 2 - itr->second->follow_angle;
float angle = itr->second->follow_angle;
@@ -258,3 +258,17 @@ void CreatureGroup::LeaderMoveTo(Position const& destination, uint32 id /*= 0*/,
member->SetHomePosition(dx, dy, dz, pathangle);
}
}
+
+bool CreatureGroup::CanLeaderStartMoving() const
+{
+ for (auto itr = m_members.begin(); itr != m_members.end(); ++itr)
+ {
+ if (itr->first != m_leader && itr->first->IsAlive())
+ {
+ if (itr->first->IsEngaged() || itr->first->IsReturningHome())
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/src/server/game/Entities/Creature/CreatureGroups.h b/src/server/game/Entities/Creature/CreatureGroups.h
index b36144db42f..52eb4eddf2a 100644
--- a/src/server/game/Entities/Creature/CreatureGroups.h
+++ b/src/server/game/Entities/Creature/CreatureGroups.h
@@ -84,6 +84,7 @@ class TC_GAME_API CreatureGroup
uint32 GetId() const { return m_groupID; }
bool isEmpty() const { return m_members.empty(); }
bool isFormed() const { return m_Formed; }
+ bool IsLeader(Creature const* creature) const { return m_leader == creature; }
void AddMember(Creature* member);
void RemoveMember(Creature* member);
@@ -91,6 +92,7 @@ class TC_GAME_API CreatureGroup
void LeaderMoveTo(Position const& destination, uint32 id = 0, uint32 moveType = 0, bool orientation = false);
void MemberEngagingTarget(Creature* member, Unit* target);
+ bool CanLeaderStartMoving() const;
};
#define sFormationMgr FormationMgr::instance()
diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp
index caa700f6672..4a39c233fc2 100644
--- a/src/server/game/Entities/Creature/GossipDef.cpp
+++ b/src/server/game/Entities/Creature/GossipDef.cpp
@@ -323,16 +323,33 @@ void QuestMenu::ClearMenu()
_questMenuItems.clear();
}
-void PlayerMenu::SendQuestGiverQuestList(QEmote const& eEmote, const std::string& Title, ObjectGuid npcGUID)
+void PlayerMenu::SendQuestGiverQuestList(QEmote const& eEmote, const std::string& Title, ObjectGuid guid)
{
WorldPacket data(SMSG_QUESTGIVER_QUEST_LIST, 100); // guess size
- data << uint64(npcGUID);
- data << Title;
- data << uint32(eEmote._Delay); // player emote
- data << uint32(eEmote._Emote); // NPC emote
+ data << uint64(guid);
+
+ if (QuestGreeting const* questGreeting = sObjectMgr->GetQuestGreeting(guid))
+ {
+ std::string strGreeting = questGreeting->greeting;
+
+ LocaleConstant localeConstant = _session->GetSessionDbLocaleIndex();
+ if (localeConstant != LOCALE_enUS)
+ if (QuestGreetingLocale const* questGreetingLocale = sObjectMgr->GetQuestGreetingLocale(MAKE_PAIR32(guid.GetEntry(), guid.GetTypeId())))
+ ObjectMgr::GetLocaleString(questGreetingLocale->greeting, localeConstant, strGreeting);
+
+ data << strGreeting;
+ data << uint32(questGreeting->greetEmoteDelay);
+ data << uint32(questGreeting->greetEmoteType);
+ }
+ else
+ {
+ data << Title;
+ data << uint32(eEmote._Delay); // player emote
+ data << uint32(eEmote._Emote); // NPC emote
+ }
size_t count_pos = data.wpos();
- data << uint8 (0);
+ data << uint8(0);
uint32 count = 0;
// Store this instead of checking the Singleton every loop iteration
@@ -340,9 +357,9 @@ void PlayerMenu::SendQuestGiverQuestList(QEmote const& eEmote, const std::string
for (uint32 i = 0; i < _questMenu.GetMenuItemCount(); ++i)
{
- QuestMenuItem const& qmi = _questMenu.GetItem(i);
+ QuestMenuItem const& questMenuItem = _questMenu.GetItem(i);
- uint32 questID = qmi.QuestId;
+ uint32 questID = questMenuItem.QuestId;
if (Quest const* quest = sObjectMgr->GetQuestTemplate(questID))
{
@@ -351,14 +368,14 @@ void PlayerMenu::SendQuestGiverQuestList(QEmote const& eEmote, const std::string
LocaleConstant localeConstant = _session->GetSessionDbLocaleIndex();
if (localeConstant != LOCALE_enUS)
- if (QuestLocale const* localeData = sObjectMgr->GetQuestLocale(questID))
- ObjectMgr::GetLocaleString(localeData->Title, localeConstant, title);
+ if (QuestLocale const* questTemplateLocaleData = sObjectMgr->GetQuestLocale(questID))
+ ObjectMgr::GetLocaleString(questTemplateLocaleData->Title, localeConstant, title);
if (questLevelInTitle)
Quest::AddQuestLevelToTitle(title, quest->GetQuestLevel());
data << uint32(questID);
- data << uint32(qmi.QuestIcon);
+ data << uint32(questMenuItem.QuestIcon);
data << int32(quest->GetQuestLevel());
data << uint32(quest->GetFlags()); // 3.3.3 quest flags
data << uint8(0); // 3.3.3 changes icon: blue question or yellow exclamation
@@ -368,7 +385,8 @@ void PlayerMenu::SendQuestGiverQuestList(QEmote const& eEmote, const std::string
data.put<uint8>(count_pos, count);
_session->SendPacket(&data);
- TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_QUEST_LIST NPC=%s", npcGUID.ToString().c_str());
+
+ TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_QUEST_LIST (QuestGiver: %s)", guid.ToString().c_str());
}
void PlayerMenu::SendQuestGiverStatus(uint8 questStatus, ObjectGuid npcGUID) const
diff --git a/src/server/game/Entities/Creature/TemporarySummon.cpp b/src/server/game/Entities/Creature/TemporarySummon.cpp
index 7e9cf6bf7a3..70a7e3446d4 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.cpp
+++ b/src/server/game/Entities/Creature/TemporarySummon.cpp
@@ -57,6 +57,7 @@ void TempSummon::Update(uint32 diff)
switch (m_type)
{
case TEMPSUMMON_MANUAL_DESPAWN:
+ case TEMPSUMMON_DEAD_DESPAWN:
break;
case TEMPSUMMON_TIMED_DESPAWN:
{
@@ -104,7 +105,7 @@ void TempSummon::Update(uint32 diff)
case TEMPSUMMON_CORPSE_DESPAWN:
{
// if m_deathState is DEAD, CORPSE was skipped
- if (m_deathState == CORPSE || m_deathState == DEAD)
+ if (m_deathState == CORPSE)
{
UnSummon();
return;
@@ -112,19 +113,9 @@ void TempSummon::Update(uint32 diff)
break;
}
- case TEMPSUMMON_DEAD_DESPAWN:
- {
- if (m_deathState == DEAD)
- {
- UnSummon();
- return;
- }
- break;
- }
case TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN:
{
- // if m_deathState is DEAD, CORPSE was skipped
- if (m_deathState == CORPSE || m_deathState == DEAD)
+ if (m_deathState == CORPSE)
{
UnSummon();
return;
@@ -146,13 +137,6 @@ void TempSummon::Update(uint32 diff)
}
case TEMPSUMMON_TIMED_OR_DEAD_DESPAWN:
{
- // if m_deathState is DEAD, CORPSE was skipped
- if (m_deathState == DEAD)
- {
- UnSummon();
- return;
- }
-
if (!IsInCombat() && IsAlive())
{
if (m_timer <= diff)
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index be0406be5b0..ce9658ef37e 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -101,7 +101,7 @@ QuaternionData QuaternionData::fromEulerAnglesZYX(float Z, float Y, float X)
}
GameObject::GameObject() : WorldObject(false), MapObject(),
- m_model(nullptr), m_goValue(), m_AI(nullptr)
+ m_model(nullptr), m_goValue(), m_AI(nullptr), m_respawnCompatibilityMode(false)
{
m_objectType |= TYPEMASK_GAMEOBJECT;
m_objectTypeId = TYPEID_GAMEOBJECT;
@@ -240,7 +240,7 @@ void GameObject::RemoveFromWorld()
}
}
-bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, uint32 phaseMask, Position const& pos, QuaternionData const& rotation, uint32 animprogress, GOState go_state, uint32 artKit /*= 0*/)
+bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, uint32 phaseMask, Position const& pos, QuaternionData const& rotation, uint32 animprogress, GOState go_state, uint32 artKit /*= 0*/, bool dynamic, ObjectGuid::LowType spawnid)
{
ASSERT(map);
SetMap(map);
@@ -253,7 +253,12 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u
return false;
}
+ // Set if this object can handle dynamic spawns
+ if (!dynamic)
+ SetRespawnCompatibilityMode();
+
SetPhaseMask(phaseMask, false);
+ UpdatePositionData();
SetZoneScript();
if (m_zoneScript)
@@ -375,6 +380,9 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u
if (map->Is25ManRaid())
loot.maxDuplicates = 3;
+ if (spawnid)
+ m_spawnId = spawnid;
+
if (uint32 linkedEntry = GetGOInfo()->GetLinkedGameObjectEntry())
{
GameObject* linkedGO = new GameObject();
@@ -486,83 +494,90 @@ void GameObject::Update(uint32 diff)
}
case GO_READY:
{
- if (m_respawnTime > 0) // timer on
+ if (m_respawnCompatibilityMode)
{
- time_t now = time(nullptr);
- if (m_respawnTime <= now) // timer expired
+ if (m_respawnTime > 0) // timer on
{
- ObjectGuid dbtableHighGuid(HighGuid::GameObject, GetEntry(), m_spawnId);
- time_t linkedRespawntime = GetMap()->GetLinkedRespawnTime(dbtableHighGuid);
- if (linkedRespawntime) // Can't respawn, the master is dead
+ time_t now = time(nullptr);
+ if (m_respawnTime <= now) // timer expired
{
- ObjectGuid targetGuid = sObjectMgr->GetLinkedRespawnGuid(dbtableHighGuid);
- if (targetGuid == dbtableHighGuid) // if linking self, never respawn (check delayed to next day)
- SetRespawnTime(DAY);
- else
- m_respawnTime = (now > linkedRespawntime ? now : linkedRespawntime) + urand(5, MINUTE); // else copy time from master and add a little
- SaveRespawnTime(); // also save to DB immediately
- return;
- }
+ ObjectGuid dbtableHighGuid(HighGuid::GameObject, GetEntry(), m_spawnId);
+ time_t linkedRespawntime = GetMap()->GetLinkedRespawnTime(dbtableHighGuid);
+ if (linkedRespawntime) // Can't respawn, the master is dead
+ {
+ ObjectGuid targetGuid = sObjectMgr->GetLinkedRespawnGuid(dbtableHighGuid);
+ if (targetGuid == dbtableHighGuid) // if linking self, never respawn
+ SetRespawnTime(WEEK);
+ else
+ m_respawnTime = (now > linkedRespawntime ? now : linkedRespawntime) + urand(5, MINUTE); // else copy time from master and add a little
+ SaveRespawnTime(); // also save to DB immediately
+ return;
+ }
- m_respawnTime = 0;
- m_SkillupList.clear();
- m_usetimes = 0;
+ m_respawnTime = 0;
+ m_SkillupList.clear();
+ m_usetimes = 0;
- // If nearby linked trap exists, respawn it
- if (GameObject* linkedTrap = GetLinkedTrap())
- linkedTrap->SetLootState(GO_READY);
+ // If nearby linked trap exists, respawn it
+ if (GameObject* linkedTrap = GetLinkedTrap())
+ linkedTrap->SetLootState(GO_READY);
- switch (GetGoType())
- {
- case GAMEOBJECT_TYPE_FISHINGNODE: // can't fish now
+ switch (GetGoType())
{
- Unit* caster = GetOwner();
- if (caster && caster->GetTypeId() == TYPEID_PLAYER)
+ case GAMEOBJECT_TYPE_FISHINGNODE: // can't fish now
{
- caster->ToPlayer()->RemoveGameObject(this, false);
-
- WorldPacket data(SMSG_FISH_ESCAPED, 0);
- caster->ToPlayer()->SendDirectMessage(&data);
+ Unit* caster = GetOwner();
+ if (caster && caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ caster->ToPlayer()->RemoveGameObject(this, false);
+
+ WorldPacket data(SMSG_FISH_ESCAPED, 0);
+ caster->ToPlayer()->SendDirectMessage(&data);
+ }
+ // can be delete
+ m_lootState = GO_JUST_DEACTIVATED;
+ return;
}
- // can be delete
- m_lootState = GO_JUST_DEACTIVATED;
- return;
+ case GAMEOBJECT_TYPE_DOOR:
+ case GAMEOBJECT_TYPE_BUTTON:
+ // We need to open doors if they are closed (add there another condition if this code breaks some usage, but it need to be here for battlegrounds)
+ if (GetGoState() != GO_STATE_READY)
+ ResetDoorOrButton();
+ break;
+ case GAMEOBJECT_TYPE_FISHINGHOLE:
+ // Initialize a new max fish count on respawn
+ m_goValue.FishingHole.MaxOpens = urand(GetGOInfo()->fishinghole.minSuccessOpens, GetGOInfo()->fishinghole.maxSuccessOpens);
+ break;
+ default:
+ break;
}
- case GAMEOBJECT_TYPE_DOOR:
- case GAMEOBJECT_TYPE_BUTTON:
- // We need to open doors if they are closed (add there another condition if this code breaks some usage, but it need to be here for battlegrounds)
- if (GetGoState() != GO_STATE_READY)
- ResetDoorOrButton();
- break;
- case GAMEOBJECT_TYPE_FISHINGHOLE:
- // Initialize a new max fish count on respawn
- m_goValue.FishingHole.MaxOpens = urand(GetGOInfo()->fishinghole.minSuccessOpens, GetGOInfo()->fishinghole.maxSuccessOpens);
- break;
- default:
- break;
- }
- // Despawn timer
- if (!m_spawnedByDefault)
- {
- // Can be despawned or destroyed
- SetLootState(GO_JUST_DEACTIVATED);
- return;
- }
+ // Despawn timer
+ if (!m_spawnedByDefault)
+ {
+ // Can be despawned or destroyed
+ SetLootState(GO_JUST_DEACTIVATED);
+ return;
+ }
- // Call AI Reset (required for example in SmartAI to clear one time events)
- if (AI())
- AI()->Reset();
+ // Call AI Reset (required for example in SmartAI to clear one time events)
+ if (AI())
+ AI()->Reset();
- // Respawn timer
- uint32 poolid = GetSpawnId() ? sPoolMgr->IsPartOfAPool<GameObject>(GetSpawnId()) : 0;
- if (poolid)
- sPoolMgr->UpdatePool<GameObject>(poolid, GetSpawnId());
- else
- GetMap()->AddToMap(this);
+ // Respawn timer
+ uint32 poolid = GetSpawnId() ? sPoolMgr->IsPartOfAPool<GameObject>(GetSpawnId()) : 0;
+ if (poolid)
+ sPoolMgr->UpdatePool<GameObject>(poolid, GetSpawnId());
+ else
+ GetMap()->AddToMap(this);
+ }
}
}
+ // Set respawn timer
+ if (!m_respawnCompatibilityMode && m_respawnTime > 0)
+ SaveRespawnTime(0, false);
+
if (isSpawned())
{
GameObjectTemplate const* goInfo = GetGOInfo();
@@ -750,6 +765,7 @@ void GameObject::Update(uint32 diff)
if (!m_respawnDelayTime)
return;
+ // ToDo: Decide if we should properly despawn these. Maybe they expect to be able to manually respawn from script?
if (!m_spawnedByDefault)
{
m_respawnTime = 0;
@@ -757,12 +773,28 @@ void GameObject::Update(uint32 diff)
return;
}
- m_respawnTime = time(nullptr) + m_respawnDelayTime;
+ uint32 respawnDelay = m_respawnDelayTime;
+ if (uint32 scalingMode = sWorld->getIntConfig(CONFIG_RESPAWN_DYNAMICMODE))
+ GetMap()->ApplyDynamicModeRespawnScaling(this, this->m_spawnId, respawnDelay, scalingMode);
+ m_respawnTime = time(nullptr) + respawnDelay;
// if option not set then object will be saved at grid unload
+ // Otherwise just save respawn time to map object memory
if (sWorld->getBoolConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY))
SaveRespawnTime();
+ if (!m_respawnCompatibilityMode)
+ {
+ // Respawn time was just saved if set to save to DB
+ // If not, we save only to map memory
+ if (!sWorld->getBoolConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY))
+ SaveRespawnTime(0, false);
+
+ // Then despawn
+ AddObjectToRemoveList();
+ return;
+ }
+
DestroyForNearbyPlayers(); // old UpdateObjectVisibility()
break;
}
@@ -848,7 +880,7 @@ void GameObject::SaveToDB()
{
// this should only be used when the gameobject has already been loaded
// preferably after adding to map, because mapid may not be valid otherwise
- GameObjectData const* data = sObjectMgr->GetGOData(m_spawnId);
+ GameObjectData const* data = sObjectMgr->GetGameObjectData(m_spawnId);
if (!data)
{
TC_LOG_ERROR("misc", "GameObject::SaveToDB failed, cannot get gameobject data!");
@@ -868,22 +900,22 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
m_spawnId = sObjectMgr->GenerateGameObjectSpawnId();
// update in loaded data (changing data only in this place)
- GameObjectData& data = sObjectMgr->NewGOData(m_spawnId);
+ GameObjectData& data = sObjectMgr->NewOrExistGameObjectData(m_spawnId);
- // data->guid = guid must not be updated at save
+ if (!data.spawnId)
+ data.spawnId = m_spawnId;
+ ASSERT(data.spawnId == m_spawnId);
data.id = GetEntry();
- data.mapid = mapid;
+ data.spawnPoint.WorldRelocate(this);
data.phaseMask = phaseMask;
- data.posX = GetPositionX();
- data.posY = GetPositionY();
- data.posZ = GetPositionZ();
- data.orientation = GetOrientation();
data.rotation = m_worldRotation;
data.spawntimesecs = m_spawnedByDefault ? m_respawnDelayTime : -(int32)m_respawnDelayTime;
data.animprogress = GetGoAnimProgress();
- data.go_state = GetGoState();
+ data.goState = GetGoState();
data.spawnMask = spawnMask;
data.artKit = GetGoArtKit();
+ if (!data.spawnGroupData)
+ data.spawnGroupData = sObjectMgr->GetDefaultSpawnGroup();
// Update in DB
SQLTransaction trans = WorldDatabase.BeginTransaction();
@@ -916,9 +948,9 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
WorldDatabase.CommitTransaction(trans);
}
-bool GameObject::LoadGameObjectFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap)
+bool GameObject::LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap, bool)
{
- GameObjectData const* data = sObjectMgr->GetGOData(spawnId);
+ GameObjectData const* data = sObjectMgr->GetGameObjectData(spawnId);
if (!data)
{
@@ -929,14 +961,14 @@ bool GameObject::LoadGameObjectFromDB(ObjectGuid::LowType spawnId, Map* map, boo
uint32 entry = data->id;
//uint32 map_id = data->mapid; // already used before call
uint32 phaseMask = data->phaseMask;
- Position pos(data->posX, data->posY, data->posZ, data->orientation);
uint32 animprogress = data->animprogress;
- GOState go_state = data->go_state;
+ GOState go_state = data->goState;
uint32 artKit = data->artKit;
m_spawnId = spawnId;
- if (!Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, phaseMask, pos, data->rotation, animprogress, go_state, artKit))
+ m_respawnCompatibilityMode = ((data->spawnGroupData->flags & SPAWNGROUP_FLAG_COMPATIBILITY_MODE) != 0);
+ if (!Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, phaseMask, data->spawnPoint, data->rotation, animprogress, go_state, artKit, !m_respawnCompatibilityMode))
return false;
if (data->spawntimesecs >= 0)
@@ -958,7 +990,7 @@ bool GameObject::LoadGameObjectFromDB(ObjectGuid::LowType spawnId, Map* map, boo
if (m_respawnTime && m_respawnTime <= time(nullptr))
{
m_respawnTime = 0;
- GetMap()->RemoveGORespawnTime(m_spawnId);
+ GetMap()->RemoveRespawnTime(SPAWN_TYPE_GAMEOBJECT, m_spawnId);
}
}
}
@@ -979,20 +1011,25 @@ bool GameObject::LoadGameObjectFromDB(ObjectGuid::LowType spawnId, Map* map, boo
void GameObject::DeleteFromDB()
{
- GetMap()->RemoveGORespawnTime(m_spawnId);
- sObjectMgr->DeleteGOData(m_spawnId);
+ GetMap()->RemoveRespawnTime(SPAWN_TYPE_GAMEOBJECT, m_spawnId);
+ sObjectMgr->DeleteGameObjectData(m_spawnId);
- PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAMEOBJECT);
+ SQLTransaction trans = WorldDatabase.BeginTransaction();
+ PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAMEOBJECT);
stmt->setUInt32(0, m_spawnId);
+ trans->Append(stmt);
- WorldDatabase.Execute(stmt);
+ stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_SPAWNGROUP_MEMBER);
+ stmt->setUInt8(0, uint8(SPAWN_TYPE_GAMEOBJECT));
+ stmt->setUInt32(1, m_spawnId);
+ trans->Append(stmt);
stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_EVENT_GAMEOBJECT);
-
stmt->setUInt32(0, m_spawnId);
+ trans->Append(stmt);
- WorldDatabase.Execute(stmt);
+ WorldDatabase.CommitTransaction(trans);
}
/*********************************************************/
@@ -1055,10 +1092,19 @@ Unit* GameObject::GetOwner() const
return ObjectAccessor::GetUnit(*this, GetOwnerGUID());
}
-void GameObject::SaveRespawnTime()
+void GameObject::SaveRespawnTime(uint32 forceDelay, bool savetodb)
{
- if (m_goData && m_goData->dbData && m_respawnTime > time(nullptr) && m_spawnedByDefault)
- GetMap()->SaveGORespawnTime(m_spawnId, m_respawnTime);
+ if (m_goData && m_respawnTime > time(nullptr) && m_spawnedByDefault)
+ {
+ if (m_respawnCompatibilityMode)
+ {
+ GetMap()->SaveRespawnTimeDB(SPAWN_TYPE_GAMEOBJECT, m_spawnId, m_respawnTime);
+ return;
+ }
+
+ uint32 thisRespawnTime = forceDelay ? time(nullptr) + forceDelay : m_respawnTime;
+ GetMap()->SaveRespawnTime(SPAWN_TYPE_GAMEOBJECT, m_spawnId, GetEntry(), thisRespawnTime, GetZoneId(), Trinity::ComputeGridCoord(GetPositionX(), GetPositionY()).GetId(), m_goData->dbData ? savetodb : false);
+ }
}
bool GameObject::IsNeverVisible() const
@@ -1123,7 +1169,7 @@ void GameObject::Respawn()
if (m_spawnedByDefault && m_respawnTime > 0)
{
m_respawnTime = time(nullptr);
- GetMap()->RemoveGORespawnTime(m_spawnId);
+ GetMap()->RemoveRespawnTime(SPAWN_TYPE_GAMEOBJECT, m_spawnId, true);
}
}
@@ -1227,7 +1273,7 @@ void GameObject::UseDoorOrButton(uint32 time_to_restore, bool alternative /* = f
void GameObject::SetGoArtKit(uint8 kit)
{
SetByteValue(GAMEOBJECT_BYTES_1, 2, kit);
- GameObjectData* data = const_cast<GameObjectData*>(sObjectMgr->GetGOData(m_spawnId));
+ GameObjectData* data = const_cast<GameObjectData*>(sObjectMgr->GetGameObjectData(m_spawnId));
if (data)
data->artKit = kit;
}
@@ -1238,10 +1284,10 @@ void GameObject::SetGoArtKit(uint8 artkit, GameObject* go, ObjectGuid::LowType l
if (go)
{
go->SetGoArtKit(artkit);
- data = go->GetGOData();
+ data = go->GetGameObjectData();
}
else if (lowguid)
- data = sObjectMgr->GetGOData(lowguid);
+ data = sObjectMgr->GetGameObjectData(lowguid);
if (data)
const_cast<GameObjectData*>(data)->artKit = artkit;
@@ -1971,8 +2017,8 @@ void GameObject::EventInform(uint32 eventId, WorldObject* invoker /*= nullptr*/)
uint32 GameObject::GetScriptId() const
{
- if (GameObjectData const* gameObjectData = GetGOData())
- if (uint32 scriptId = gameObjectData->ScriptId)
+ if (GameObjectData const* gameObjectData = GetGameObjectData())
+ if (uint32 scriptId = gameObjectData->scriptId)
return scriptId;
return GetGOInfo()->ScriptId;
@@ -2410,24 +2456,20 @@ void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* t
void GameObject::GetRespawnPosition(float &x, float &y, float &z, float* ori /* = nullptr*/) const
{
- if (m_spawnId)
+ if (m_goData)
{
- if (GameObjectData const* data = sObjectMgr->GetGOData(GetSpawnId()))
- {
- x = data->posX;
- y = data->posY;
- z = data->posZ;
- if (ori)
- *ori = data->orientation;
- return;
- }
+ if (ori)
+ m_goData->spawnPoint.GetPosition(x, y, z, *ori);
+ else
+ m_goData->spawnPoint.GetPosition(x, y, z);
+ }
+ else
+ {
+ if (ori)
+ GetPosition(x, y, z, *ori);
+ else
+ GetPosition(x, y, z);
}
-
- x = GetPositionX();
- y = GetPositionY();
- z = GetPositionZ();
- if (ori)
- *ori = GetOrientation();
}
float GameObject::GetInteractionDistance() const
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index 3080bd94860..784af8fda27 100644
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -89,11 +89,11 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
void RemoveFromWorld() override;
void CleanupsBeforeDelete(bool finalCleanup = true) override;
- bool Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, uint32 phaseMask, Position const& pos, QuaternionData const& rotation, uint32 animprogress, GOState go_state, uint32 artKit = 0);
+ bool Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, uint32 phaseMask, Position const& pos, QuaternionData const& rotation, uint32 animprogress, GOState go_state, uint32 artKit = 0, bool dynamic = false, ObjectGuid::LowType spawnid = 0);
void Update(uint32 p_time) override;
GameObjectTemplate const* GetGOInfo() const { return m_goInfo; }
GameObjectTemplateAddon const* GetTemplateAddon() const { return m_goTemplateAddon; }
- GameObjectData const* GetGOData() const { return m_goData; }
+ GameObjectData const* GetGameObjectData() const { return m_goData; }
GameObjectValue const* GetGOValue() const { return &m_goValue; }
bool IsTransport() const;
@@ -113,8 +113,7 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
void SaveToDB();
void SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask);
- bool LoadFromDB(ObjectGuid::LowType spawnId, Map* map) { return LoadGameObjectFromDB(spawnId, map, false); }
- bool LoadGameObjectFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap = true);
+ bool LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap, bool = true); // arg4 is unused, only present to match the signature on Creature
void DeleteFromDB();
void SetOwnerGUID(ObjectGuid owner)
@@ -212,7 +211,7 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
uint32 GetUseCount() const { return m_usetimes; }
uint32 GetUniqueUseCount() const { return m_unique_users.size(); }
- void SaveRespawnTime() override;
+ void SaveRespawnTime(uint32 forceDelay = 0, bool savetodb = true) override;
Loot loot;
@@ -264,6 +263,10 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
void EventInform(uint32 eventId, WorldObject* invoker = nullptr);
+ // There's many places not ready for dynamic spawns. This allows them to live on for now.
+ void SetRespawnCompatibilityMode(bool mode = true) { m_respawnCompatibilityMode = mode; }
+ bool GetRespawnCompatibilityMode() {return m_respawnCompatibilityMode; }
+
uint32 GetScriptId() const;
GameObjectAI* AI() const { return m_AI; }
@@ -344,5 +347,6 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
return IsInRange(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), dist2compare);
}
GameObjectAI* m_AI;
+ bool m_respawnCompatibilityMode;
};
#endif
diff --git a/src/server/game/Entities/GameObject/GameObjectData.h b/src/server/game/Entities/GameObject/GameObjectData.h
index e2d2f27e5b5..6e1a07786f9 100644
--- a/src/server/game/Entities/GameObject/GameObjectData.h
+++ b/src/server/game/Entities/GameObject/GameObjectData.h
@@ -20,6 +20,7 @@
#include "Common.h"
#include "SharedDefines.h"
+#include "SpawnData.h"
#include "WorldPacket.h"
#include <string>
#include <vector>
@@ -593,26 +594,14 @@ struct GameObjectAddon
uint32 InvisibilityValue;
};
-// from `gameobject`
-struct GameObjectData
+// `gameobject` table
+struct GameObjectData : public SpawnData
{
- explicit GameObjectData() : id(0), mapid(0), phaseMask(0), posX(0.0f), posY(0.0f), posZ(0.0f), orientation(0.0f), spawntimesecs(0),
- animprogress(0), go_state(GO_STATE_ACTIVE), spawnMask(0), artKit(0), ScriptId(0), dbData(true) { }
- uint32 id; // entry in gamobject_template
- uint16 mapid;
- uint32 phaseMask;
- float posX;
- float posY;
- float posZ;
- float orientation;
+ GameObjectData() : SpawnData(SPAWN_TYPE_GAMEOBJECT) { }
QuaternionData rotation;
- int32 spawntimesecs;
- uint32 animprogress;
- GOState go_state;
- uint8 spawnMask;
- uint8 artKit;
- uint32 ScriptId;
- bool dbData;
+ uint32 animprogress = 0;
+ GOState goState = GO_STATE_ACTIVE;
+ uint8 artKit = 0;
};
#endif // GameObjectData_h__
diff --git a/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp b/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp
index 50e0805797c..1468d168ffa 100644
--- a/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp
+++ b/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp
@@ -76,7 +76,7 @@ void LoadRandomEnchantmentsTable()
TC_LOG_INFO("server.loading", ">> Loaded %u Item Enchantment definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
else
- TC_LOG_ERROR("server.loading", ">> Loaded 0 Item Enchantment definitions. DB table `item_enchantment_template` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 Item Enchantment definitions. DB table `item_enchantment_template` is empty.");
}
uint32 GetItemEnchantMod(int32 entry)
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 508a89a86c8..9e2546f2df7 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -1105,7 +1105,7 @@ void WorldObject::RemoveFromWorld()
Object::RemoveFromWorld();
}
-InstanceScript* WorldObject::GetInstanceScript()
+InstanceScript* WorldObject::GetInstanceScript() const
{
Map* map = GetMap();
return map->IsDungeon() ? ((InstanceMap*)map)->GetInstanceScript() : nullptr;
@@ -1908,7 +1908,7 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
break;
}
- if (!summon->Create(GenerateLowGuid<HighGuid::Unit>(), this, phase, entry, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), nullptr, vehId))
+ if (!summon->Create(GenerateLowGuid<HighGuid::Unit>(), this, phase, entry, pos, nullptr, vehId, true))
{
delete summon;
return nullptr;
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index ca1b547f68b..b6cee547126 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -291,7 +291,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation
uint32 GetAreaId() const { return m_areaId; }
void GetZoneAndAreaId(uint32& zoneid, uint32& areaid) const { zoneid = m_zoneId, areaid = m_areaId; }
- InstanceScript* GetInstanceScript();
+ InstanceScript* GetInstanceScript() const;
std::string const& GetName() const { return m_name; }
void SetName(std::string const& newname) { m_name = newname; }
@@ -342,7 +342,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation
void SendObjectDeSpawnAnim(ObjectGuid guid);
- virtual void SaveRespawnTime() { }
+ virtual void SaveRespawnTime(uint32 /*forceDelay*/ = 0, bool /*saveToDB*/ = true) { }
void AddObjectToRemoveList();
float GetGridActivationRange() const;
diff --git a/src/server/game/Entities/Object/ObjectGuid.cpp b/src/server/game/Entities/Object/ObjectGuid.cpp
index 3a26dfd0d7f..71837474ca9 100644
--- a/src/server/game/Entities/Object/ObjectGuid.cpp
+++ b/src/server/game/Entities/Object/ObjectGuid.cpp
@@ -98,6 +98,14 @@ void ObjectGuidGeneratorBase::HandleCounterOverflow(HighGuid high)
World::StopNow(ERROR_EXIT_CODE);
}
+void ObjectGuidGeneratorBase::CheckGuidTrigger(ObjectGuid::LowType guidlow)
+{
+ if (!sWorld->IsGuidAlert() && guidlow > sWorld->getIntConfig(CONFIG_RESPAWN_GUIDALERTLEVEL))
+ sWorld->TriggerGuidAlert();
+ else if (!sWorld->IsGuidWarning() && guidlow > sWorld->getIntConfig(CONFIG_RESPAWN_GUIDWARNLEVEL))
+ sWorld->TriggerGuidWarning();
+}
+
#define GUID_TRAIT_INSTANTIATE_GUID( HIGH_GUID ) \
template class TC_GAME_API ObjectGuidGenerator< HIGH_GUID >;
diff --git a/src/server/game/Entities/Object/ObjectGuid.h b/src/server/game/Entities/Object/ObjectGuid.h
index 75410aa4f28..d1e34d3a38c 100644
--- a/src/server/game/Entities/Object/ObjectGuid.h
+++ b/src/server/game/Entities/Object/ObjectGuid.h
@@ -287,6 +287,7 @@ public:
protected:
static void HandleCounterOverflow(HighGuid high);
+ static void CheckGuidTrigger(ObjectGuid::LowType guid);
ObjectGuid::LowType _nextGuid;
};
@@ -300,6 +301,10 @@ public:
{
if (_nextGuid >= ObjectGuid::GetMaxCounter(high) - 1)
HandleCounterOverflow(high);
+
+ if (high == HighGuid::Unit || high == HighGuid::GameObject)
+ CheckGuidTrigger(_nextGuid);
+
return _nextGuid++;
}
};
diff --git a/src/server/game/Entities/Object/Position.h b/src/server/game/Entities/Object/Position.h
index 98cb82df2e1..11867c6fed6 100644
--- a/src/server/game/Entities/Object/Position.h
+++ b/src/server/game/Entities/Object/Position.h
@@ -207,15 +207,9 @@ public:
return GetExactDist2dSq(pos) < dist * dist;
}
- bool IsInDist(float x, float y, float z, float dist) const
- {
- return GetExactDistSq(x, y, z) < dist * dist;
- }
-
- bool IsInDist(Position const* pos, float dist) const
- {
- return GetExactDistSq(pos) < dist * dist;
- }
+ bool IsInDist(float x, float y, float z, float dist) const { return GetExactDistSq(x, y, z) < dist * dist; }
+ bool IsInDist(Position const& pos, float dist) const { return GetExactDistSq(pos) < dist * dist; }
+ bool IsInDist(Position const* pos, float dist) const { return GetExactDistSq(pos) < dist * dist; }
bool IsWithinBox(Position const& center, float xradius, float yradius, float zradius) const;
@@ -245,15 +239,12 @@ class WorldLocation : public Position
WorldLocation(WorldLocation const& loc)
: Position(loc), m_mapId(loc.GetMapId()) { }
- void WorldRelocate(WorldLocation const& loc)
- {
- m_mapId = loc.GetMapId();
- Relocate(loc);
- }
-
- void WorldRelocate(uint32 _mapId = MAPID_INVALID, float x = 0.f, float y = 0.f, float z = 0.f, float o = 0.f)
+ void WorldRelocate(WorldLocation const& loc) { m_mapId = loc.GetMapId(); Relocate(loc); }
+ void WorldRelocate(WorldLocation const* loc) { m_mapId = loc->GetMapId(); Relocate(loc); }
+ void WorldRelocate(uint32 mapId, Position const& pos) { m_mapId = mapId; Relocate(pos); }
+ void WorldRelocate(uint32 mapId = MAPID_INVALID, float x = 0.f, float y = 0.f, float z = 0.f, float o = 0.f)
{
- m_mapId = _mapId;
+ m_mapId = mapId;
Relocate(x, y, z, o);
}
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index 20f9e57b666..6890113178a 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -1306,24 +1306,22 @@ bool Pet::addSpell(uint32 spellId, ActiveStates active /*= ACT_DECIDE*/, PetSpel
if (itr != m_spells.end())
{
if (itr->second.state == PETSPELL_REMOVED)
- {
- m_spells.erase(itr);
state = PETSPELL_CHANGED;
- }
- else if (state == PETSPELL_UNCHANGED && itr->second.state != PETSPELL_UNCHANGED)
+ else
{
- // can be in case spell loading but learned at some previous spell loading
- itr->second.state = PETSPELL_UNCHANGED;
+ if (state == PETSPELL_UNCHANGED && itr->second.state != PETSPELL_UNCHANGED)
+ {
+ // can be in case spell loading but learned at some previous spell loading
+ itr->second.state = PETSPELL_UNCHANGED;
- if (active == ACT_ENABLED)
- ToggleAutocast(spellInfo, true);
- else if (active == ACT_DISABLED)
- ToggleAutocast(spellInfo, false);
+ if (active == ACT_ENABLED)
+ ToggleAutocast(spellInfo, true);
+ else if (active == ACT_DISABLED)
+ ToggleAutocast(spellInfo, false);
+ }
return false;
}
- else
- return false;
}
PetSpell newspell;
@@ -1520,7 +1518,7 @@ bool Pet::removeSpell(uint32 spell_id, bool learn_prev, bool clear_ab)
}
// if remove last rank or non-ranked then update action bar at server and client if need
- if (m_charmInfo->RemoveSpellFromActionBar(spell_id) && !learn_prev && clear_ab)
+ if (clear_ab && !learn_prev && m_charmInfo->RemoveSpellFromActionBar(spell_id))
{
if (!m_loading)
GetOwner()->PetSpellInitialize(); // need update action bar for last removed rank
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 032c02f2288..7bf4e185efd 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -176,6 +176,7 @@ Player::Player(WorldSession* session): Unit(true)
m_session = session;
m_ingametime = 0;
+ m_sharedQuestId = 0;
m_ExtraFlags = 0;
@@ -490,6 +491,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo
}
SetMap(sMapMgr->CreateMap(info->mapId, this));
+ UpdatePositionData();
uint8 powertype = cEntry->powerType;
@@ -6444,6 +6446,12 @@ void Player::CheckAreaExploreAndOutdoor()
XP = uint32(sObjectMgr->GetBaseXP(areaEntry->area_level)*sWorld->getRate(RATE_XP_EXPLORE));
}
+ if (sWorld->getIntConfig(CONFIG_MIN_DISCOVERED_SCALED_XP_RATIO))
+ {
+ uint32 minScaledXP = uint32(sObjectMgr->GetBaseXP(areaEntry->area_level)*sWorld->getRate(RATE_XP_EXPLORE)) * sWorld->getIntConfig(CONFIG_MIN_DISCOVERED_SCALED_XP_RATIO) / 100;
+ XP = std::max(minScaledXP, XP);
+ }
+
GiveXP(XP, nullptr);
SendExplorationExperience(areaId, XP);
}
@@ -6993,24 +7001,25 @@ void Player::UpdateArea(uint32 newArea)
void Player::UpdateZone(uint32 newZone, uint32 newArea)
{
- if (m_zoneUpdateId != newZone)
+ if (!IsInWorld())
+ return;
+ uint32 const oldZone = m_zoneUpdateId;
+ m_zoneUpdateId = newZone;
+ m_zoneUpdateTimer = ZONE_UPDATE_INTERVAL;
+
+ GetMap()->UpdatePlayerZoneStats(oldZone, newZone);
+
+ // call leave script hooks immedately (before updating flags)
+ if (oldZone != newZone)
{
sOutdoorPvPMgr->HandlePlayerLeaveZone(this, m_zoneUpdateId);
- sOutdoorPvPMgr->HandlePlayerEnterZone(this, newZone);
sBattlefieldMgr->HandlePlayerLeaveZone(this, m_zoneUpdateId);
- sBattlefieldMgr->HandlePlayerEnterZone(this, newZone);
- SendInitWorldStates(newZone, newArea); // only if really enters to new zone, not just area change, works strange...
- if (Guild* guild = GetGuild())
- guild->UpdateMemberData(this, GUILD_MEMBER_DATA_ZONEID, newZone);
}
// group update
if (GetGroup())
SetGroupUpdateFlag(GROUP_UPDATE_FULL);
- m_zoneUpdateId = newZone;
- m_zoneUpdateTimer = ZONE_UPDATE_INTERVAL;
-
// zone changed, so area changed as well, update it
UpdateArea(newArea);
@@ -7027,8 +7036,6 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
WeatherMgr::SendFineWeatherUpdateToPlayer(this);
}
- sScriptMgr->OnPlayerUpdateZone(this, newZone, newArea);
-
// in PvP, any not controlled zone (except zone->team == 6, default case)
// in PvE, only opposition team capital
switch (zone->team)
@@ -7075,6 +7082,17 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
UpdateLocalChannels(newZone);
UpdateZoneDependentAuras(newZone);
+
+ // call enter script hooks after everyting else has processed
+ sScriptMgr->OnPlayerUpdateZone(this, newZone, newArea);
+ if (oldZone != newZone)
+ {
+ sOutdoorPvPMgr->HandlePlayerEnterZone(this, newZone);
+ sBattlefieldMgr->HandlePlayerEnterZone(this, newZone);
+ SendInitWorldStates(newZone, newArea); // only if really enters to new zone, not just area change, works strange...
+ if (Guild* guild = GetGuild())
+ guild->UpdateMemberData(this, GUILD_MEMBER_DATA_ZONEID, newZone);
+ }
}
//If players are too far away from the duel flag... they lose the duel
@@ -11194,6 +11212,9 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool
if (HasUnitState(UNIT_STATE_STUNNED))
return EQUIP_ERR_YOU_ARE_STUNNED;
+ if (IsCharmed())
+ return EQUIP_ERR_CANT_DO_RIGHT_NOW; // @todo is this the correct error?
+
// do not allow equipping gear except weapons, offhands, projectiles, relics in
// - combat
// - in-progress arenas
@@ -11351,6 +11372,9 @@ InventoryResult Player::CanUnequipItem(uint16 pos, bool swap) const
if (pItem->m_lootGenerated)
return EQUIP_ERR_ALREADY_LOOTED;
+ if (IsCharmed())
+ return EQUIP_ERR_CANT_DO_RIGHT_NOW; // @todo is this the correct error?
+
// do not allow unequipping gear except weapons, offhands, projectiles, relics in
// - combat
// - in-progress arenas
@@ -11775,14 +11799,11 @@ void Player::SetAmmo(uint32 item)
return;
// check ammo
- if (item)
+ InventoryResult msg = CanUseAmmo(item);
+ if (msg != EQUIP_ERR_OK)
{
- InventoryResult msg = CanUseAmmo(item);
- if (msg != EQUIP_ERR_OK)
- {
- SendEquipError(msg, nullptr, nullptr, item);
- return;
- }
+ SendEquipError(msg, nullptr, nullptr, item);
+ return;
}
SetUInt32Value(PLAYER_AMMO_ID, item);
@@ -13984,7 +14005,7 @@ void Player::SendItemDurations()
}
}
-void Player::SendNewItem(Item* item, uint32 count, bool received, bool created, bool broadcast)
+void Player::SendNewItem(Item* item, uint32 count, bool received, bool created, bool broadcast, bool sendChatMessage)
{
if (!item) // prevent crash
return;
@@ -13994,7 +14015,7 @@ void Player::SendNewItem(Item* item, uint32 count, bool received, bool created,
data << uint64(GetGUID()); // player GUID
data << uint32(received); // 0=looted, 1=from npc
data << uint32(created); // 0=received, 1=created
- data << uint32(1); // bool print error to chat
+ data << uint32(sendChatMessage); // bool print message to chat
data << uint8(item->GetBagSlot()); // bagslot
// item slot, but when added to stack: 0xFFFFFFFF
data << uint32((item->GetCount() == count) ? item->GetSlot() : -1);
@@ -15009,7 +15030,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
if (CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemId, quest->RewardItemIdCount[i]) == EQUIP_ERR_OK)
{
Item* item = StoreNewItem(dest, itemId, true, GenerateItemRandomPropertyId(itemId));
- SendNewItem(item, quest->RewardItemIdCount[i], true, false);
+ SendNewItem(item, quest->RewardItemIdCount[i], true, false, false, false);
}
else if (quest->IsDFQuest())
SendItemRetrievalMail(itemId, quest->RewardItemIdCount[i]);
@@ -15025,7 +15046,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
if (CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemId, quest->RewardChoiceItemCount[reward]) == EQUIP_ERR_OK)
{
Item* item = StoreNewItem(dest, itemId, true, GenerateItemRandomPropertyId(itemId));
- SendNewItem(item, quest->RewardChoiceItemCount[reward], true, false);
+ SendNewItem(item, quest->RewardChoiceItemCount[reward], true, false, false, false);
}
}
}
@@ -15502,7 +15523,7 @@ bool Player::SatisfyQuestStatus(Quest const* qInfo, bool msg) const
bool Player::SatisfyQuestConditions(Quest const* qInfo, bool msg)
{
- if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_QUEST_ACCEPT, qInfo->GetQuestId(), this))
+ if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_QUEST_AVAILABLE, qInfo->GetQuestId(), this))
{
if (msg)
{
@@ -15901,7 +15922,7 @@ QuestGiverStatus Player::GetQuestDialogStatus(Object* questgiver)
if (!quest)
continue;
- if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_QUEST_ACCEPT, quest->GetQuestId(), this))
+ if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_QUEST_AVAILABLE, quest->GetQuestId(), this))
continue;
QuestStatus status = GetQuestStatus(questId);
@@ -17148,7 +17169,6 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
//join player to battleground group
currentBg->EventPlayerLoggedIn(this);
- currentBg->AddOrSetPlayerToCorrectBgGroup(this, m_bgData.bgTeam);
SetInviteForBattlegroundQueueType(bgQueueTypeId, currentBg->GetInstanceID());
}
@@ -17373,6 +17393,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
SetMap(map);
StoreRaidMapDifficulty();
+ UpdatePositionData();
// now that map position is determined, check instance validity
if (!CheckInstanceValidity(true) && !IsInstanceLoginGameMasterException())
@@ -21217,7 +21238,14 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
uint32 money = GetMoney();
if (npc)
- totalcost = (uint32)ceil(totalcost*GetReputationPriceDiscount(npc));
+ {
+ float discount = GetReputationPriceDiscount(npc);
+ totalcost = uint32(ceil(totalcost * discount));
+ firstcost = uint32(ceil(firstcost * discount));
+ m_taxi.SetFlightMasterFactionTemplateId(npc->GetFaction());
+ }
+ else
+ m_taxi.SetFlightMasterFactionTemplateId(0);
if (money < totalcost)
{
@@ -21325,6 +21353,27 @@ void Player::ContinueTaxiFlight() const
GetSession()->SendDoFlight(mountDisplayId, path, startNode);
}
+void Player::SendTaxiNodeStatusMultiple()
+{
+ for (auto itr = m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr)
+ {
+ if (!itr->IsCreature())
+ continue;
+ Creature* creature = ObjectAccessor::GetCreature(*this, *itr);
+ if (!creature || creature->IsHostileTo(this))
+ continue;
+ if (!creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_FLIGHTMASTER))
+ continue;
+ uint32 nearestNode = sObjectMgr->GetNearestTaxiNode(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetMapId(), GetTeam());
+ if (!nearestNode)
+ continue;
+ WorldPacket data(SMSG_TAXINODE_STATUS, 9);
+ data << *itr;
+ data << uint8(m_taxi.IsTaximaskNodeKnown(nearestNode) ? 1 : 0);
+ SendDirectMessage(&data);
+ }
+}
+
void Player::InitDataForForm(bool reapplyMods)
{
ShapeshiftForm form = GetShapeshiftForm();
@@ -22517,6 +22566,8 @@ void Player::SendInitialPacketsAfterAddToMap()
SendAurasForTarget(this);
SendEnchantmentDurations(); // must be after add to map
SendItemDurations(); // must be after add to map
+ SendQuestGiverStatusMultiple();
+ SendTaxiNodeStatusMultiple();
// raid downscaling - send difficulty to player
if (GetMap()->IsRaid())
@@ -23168,11 +23219,15 @@ bool Player::GetBGAccessByLevel(BattlegroundTypeId bgTypeId) const
float Player::GetReputationPriceDiscount(Creature const* creature) const
{
- FactionTemplateEntry const* vendor_faction = creature->GetFactionTemplateEntry();
- if (!vendor_faction || !vendor_faction->faction)
+ return GetReputationPriceDiscount(creature->GetFactionTemplateEntry());
+}
+
+float Player::GetReputationPriceDiscount(FactionTemplateEntry const* factionTemplate) const
+{
+ if (!factionTemplate || !factionTemplate->faction)
return 1.0f;
- ReputationRank rank = GetReputationRank(vendor_faction->faction);
+ ReputationRank rank = GetReputationRank(factionTemplate->faction);
if (rank <= REP_NEUTRAL)
return 1.0f;
@@ -23557,7 +23612,7 @@ bool Player::isHonorOrXPTarget(Unit* victim) const
uint8 k_grey = Trinity::XP::GetGrayLevel(getLevel());
// Victim level less gray level
- if (v_level <= k_grey)
+ if (v_level <= k_grey && !sWorld->getIntConfig(CONFIG_MIN_CREATURE_SCALED_XP_RATIO))
return false;
if (Creature const* creature = victim->ToCreature())
@@ -24030,7 +24085,7 @@ void Player::ProcessTerrainStatusUpdate(ZLiquidStatus status, Optional<LiquidDat
else
m_MirrorTimerFlags &= ~UNDERWATER_INLAVA;
}
-
+
// Slime state (any contact)
if (liquidData->type_flags & MAP_LIQUID_TYPE_SLIME)
{
@@ -26240,9 +26295,6 @@ bool Player::SetDisableGravity(bool disable, bool packetOnly /*= false*/)
bool Player::SetCanFly(bool apply, bool packetOnly /*= false*/)
{
- if (!packetOnly && !Unit::SetCanFly(apply))
- return false;
-
if (!apply)
SetFallInformation(0, GetPositionZ());
@@ -26251,11 +26303,16 @@ bool Player::SetCanFly(bool apply, bool packetOnly /*= false*/)
data << uint32(0); //! movement counter
SendDirectMessage(&data);
- data.Initialize(MSG_MOVE_UPDATE_CAN_FLY, 64);
- data << GetPackGUID();
- BuildMovementPacket(&data);
- SendMessageToSet(&data, false);
- return true;
+ if (packetOnly || Unit::SetCanFly(apply))
+ {
+ data.Initialize(MSG_MOVE_UPDATE_CAN_FLY, 64);
+ data << GetPackGUID();
+ BuildMovementPacket(&data);
+ SendMessageToSet(&data, false);
+ return true;
+ }
+ else
+ return false;
}
bool Player::SetHover(bool apply, bool packetOnly /*= false*/)
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 4a2a82000b4..bc72066307f 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -946,6 +946,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
bool ActivateTaxiPathTo(uint32 taxi_path_id, uint32 spellid = 0);
void CleanupAfterTaxiFlight();
void ContinueTaxiFlight() const;
+ void SendTaxiNodeStatusMultiple();
// mount_id can be used in scripting calls
bool isAcceptWhispers() const { return (m_ExtraFlags & PLAYER_EXTRA_ACCEPT_WHISPERS) != 0; }
void SetAcceptWhispers(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_ACCEPT_WHISPERS; else m_ExtraFlags &= ~PLAYER_EXTRA_ACCEPT_WHISPERS; }
@@ -1120,11 +1121,12 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
bool IsUseEquipedWeapon(bool mainhand) const;
bool IsTwoHandUsed() const;
bool IsUsingTwoHandedWeaponInOneHand() const;
- void SendNewItem(Item* item, uint32 count, bool received, bool created, bool broadcast = false);
+ void SendNewItem(Item* item, uint32 count, bool received, bool created, bool broadcast = false, bool sendChatMessage = true);
bool BuyItemFromVendorSlot(ObjectGuid vendorguid, uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot);
bool _StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot, int32 price, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore);
float GetReputationPriceDiscount(Creature const* creature) const;
+ float GetReputationPriceDiscount(FactionTemplateEntry const* factionTemplate) const;
Player* GetTrader() const;
TradeData* GetTradeData() const { return m_trade; }
diff --git a/src/server/game/Entities/Player/PlayerTaxi.cpp b/src/server/game/Entities/Player/PlayerTaxi.cpp
index 9a53838e4a9..74a11230d4e 100644
--- a/src/server/game/Entities/Player/PlayerTaxi.cpp
+++ b/src/server/game/Entities/Player/PlayerTaxi.cpp
@@ -91,9 +91,13 @@ bool PlayerTaxi::LoadTaxiDestinationsFromString(const std::string& values, uint3
{
ClearTaxiDestinations();
- Tokenizer Tokenizer(values, ' ');
+ Tokenizer tokens(values, ' ');
+ auto iter = tokens.begin();
+ if (iter != tokens.end())
+ m_flightMasterFactionId = atoul(*iter);
- for (Tokenizer::const_iterator iter = Tokenizer.begin(); iter != Tokenizer.end(); ++iter)
+ ++iter;
+ for (; iter != tokens.end(); ++iter)
{
uint32 node = atoul(*iter);
AddTaxiDestination(node);
@@ -128,6 +132,7 @@ std::string PlayerTaxi::SaveTaxiDestinationsToString()
return "";
std::ostringstream ss;
+ ss << m_flightMasterFactionId << ' ';
for (size_t i = 0; i < m_TaxiDestinations.size(); ++i)
ss << m_TaxiDestinations[i] << ' ';
@@ -154,3 +159,8 @@ std::ostringstream& operator<<(std::ostringstream& ss, PlayerTaxi const& taxi)
ss << taxi.m_taximask[i] << ' ';
return ss;
}
+
+FactionTemplateEntry const* PlayerTaxi::GetFlightMasterFactionTemplate() const
+{
+ return sFactionTemplateStore.LookupEntry(m_flightMasterFactionId);
+}
diff --git a/src/server/game/Entities/Player/PlayerTaxi.h b/src/server/game/Entities/Player/PlayerTaxi.h
index ae5052b3e7a..a4791c0ff4e 100644
--- a/src/server/game/Entities/Player/PlayerTaxi.h
+++ b/src/server/game/Entities/Player/PlayerTaxi.h
@@ -24,11 +24,12 @@
#include <iosfwd>
class ByteBuffer;
+struct FactionTemplateEntry;
class TC_GAME_API PlayerTaxi
{
public:
- PlayerTaxi() { m_taximask.fill(0); }
+ PlayerTaxi() : m_flightMasterFactionId(0) { m_taximask.fill(0); }
~PlayerTaxi() { }
// Nodes
void InitTaxiNodesForLevel(uint32 race, uint32 chrClass, uint8 level);
@@ -71,11 +72,14 @@ class TC_GAME_API PlayerTaxi
std::deque<uint32> const& GetPath() const { return m_TaxiDestinations; }
bool empty() const { return m_TaxiDestinations.empty(); }
+ FactionTemplateEntry const* GetFlightMasterFactionTemplate() const;
+ void SetFlightMasterFactionTemplateId(uint32 factionTemplateId) { m_flightMasterFactionId = factionTemplateId; }
friend std::ostringstream& operator<<(std::ostringstream& ss, PlayerTaxi const& taxi);
private:
TaxiMask m_taximask;
std::deque<uint32> m_TaxiDestinations;
+ uint32 m_flightMasterFactionId;
};
std::ostringstream& operator<<(std::ostringstream& ss, PlayerTaxi const& taxi);
diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp
index 6d36095ee7d..2b9b82b392b 100644
--- a/src/server/game/Entities/Transport/Transport.cpp
+++ b/src/server/game/Entities/Transport/Transport.cpp
@@ -302,16 +302,14 @@ Creature* Transport::CreateNPCPassenger(ObjectGuid::LowType guid, CreatureData c
Map* map = GetMap();
Creature* creature = new Creature();
- if (!creature->LoadCreatureFromDB(guid, map, false))
+ if (!creature->LoadFromDB(guid, map, false, true))
{
delete creature;
return nullptr;
}
- float x = data->posX;
- float y = data->posY;
- float z = data->posZ;
- float o = data->orientation;
+ float x, y, z, o;
+ data->spawnPoint.GetPosition(x, y, z, o);
creature->SetTransport(this);
creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
@@ -349,7 +347,7 @@ GameObject* Transport::CreateGOPassenger(ObjectGuid::LowType guid, GameObjectDat
Map* map = GetMap();
GameObject* go = new GameObject();
- if (!go->LoadGameObjectFromDB(guid, map, false))
+ if (!go->LoadFromDB(guid, map, false))
{
delete go;
return nullptr;
@@ -357,10 +355,8 @@ GameObject* Transport::CreateGOPassenger(ObjectGuid::LowType guid, GameObjectDat
ASSERT(data);
- float x = data->posX;
- float y = data->posY;
- float z = data->posZ;
- float o = data->orientation;
+ float x, y, z, o;
+ data->spawnPoint.GetPosition(x, y, z, o);
go->SetTransport(this);
go->m_movementInfo.transport.guid = GetGUID();
@@ -468,7 +464,7 @@ TempSummon* Transport::SummonPassenger(uint32 entry, Position const& pos, TempSu
pos.GetPosition(x, y, z, o);
CalculatePassengerPosition(x, y, z, &o);
- if (!summon->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, phase, entry, x, y, z, o, nullptr, vehId))
+ if (!summon->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, phase, entry, { x, y, z, o }, nullptr, vehId))
{
delete summon;
return nullptr;
@@ -545,7 +541,7 @@ void Transport::LoadStaticPassengers()
// GameObjects on transport
guidEnd = cellItr->second.gameobjects.end();
for (CellGuidSet::const_iterator guidItr = cellItr->second.gameobjects.begin(); guidItr != guidEnd; ++guidItr)
- CreateGOPassenger(*guidItr, sObjectMgr->GetGOData(*guidItr));
+ CreateGOPassenger(*guidItr, sObjectMgr->GetGameObjectData(*guidItr));
}
}
}
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 733c3231915..bd4c71c06e6 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -40,6 +40,7 @@
#include "Log.h"
#include "LootMgr.h"
#include "MotionMaster.h"
+#include "MovementGenerator.h"
#include "MoveSpline.h"
#include "MoveSplineInit.h"
#include "ObjectAccessor.h"
@@ -2607,7 +2608,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo
SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spellInfo) const
{
// Can`t miss on dead target (on skinning for example)
- if ((!victim->IsAlive() && victim->GetTypeId() != TYPEID_PLAYER))
+ if (!victim->IsAlive() && victim->GetTypeId() != TYPEID_PLAYER)
return SPELL_MISS_NONE;
SpellSchoolMask schoolMask = spellInfo->GetSchoolMask();
@@ -3391,7 +3392,8 @@ void Unit::ProcessTerrainStatusUpdate(ZLiquidStatus status, Optional<LiquidData>
{
if (_lastLiquid && _lastLiquid->SpellId)
RemoveAurasDueToSpell(_lastLiquid->SpellId);
- if (curLiquid && curLiquid->SpellId)
+ Player* player = GetCharmerOrOwnerPlayerOrPlayerItself();
+ if (curLiquid && curLiquid->SpellId && (!player || !player->IsGameMaster()))
CastSpell(this, curLiquid->SpellId, true);
_lastLiquid = curLiquid;
}
@@ -5675,8 +5677,6 @@ ReputationRank Unit::GetFactionReactionTo(FactionTemplateEntry const* factionTem
return REP_NEUTRAL;
FactionTemplateEntry const* targetFactionTemplateEntry = target->GetFactionTemplateEntry();
- if (!targetFactionTemplateEntry)
- return REP_NEUTRAL;
if (Player const* targetPlayerOwner = target->GetAffectingPlayer())
{
@@ -5728,7 +5728,7 @@ bool Unit::IsFriendlyTo(Unit const* unit) const
bool Unit::IsHostileToPlayers() const
{
FactionTemplateEntry const* my_faction = GetFactionTemplateEntry();
- if (!my_faction || !my_faction->faction)
+ if (!my_faction->faction)
return false;
FactionEntry const* raw_faction = sFactionStore.LookupEntry(my_faction->faction);
@@ -5741,7 +5741,7 @@ bool Unit::IsHostileToPlayers() const
bool Unit::IsNeutralToAll() const
{
FactionTemplateEntry const* my_faction = GetFactionTemplateEntry();
- if (!my_faction || !my_faction->faction)
+ if (!my_faction->faction)
return true;
FactionEntry const* raw_faction = sFactionStore.LookupEntry(my_faction->faction);
@@ -9683,11 +9683,10 @@ Unit* Creature::SelectVictim()
// last case when creature must not go to evade mode:
// it in combat but attacker not make any damage and not enter to aggro radius to have record in threat list
- // for example at owner command to pet attack some far away creature
// Note: creature does not have targeted movement generator but has attacker in this case
for (AttackerSet::const_iterator itr = m_attackers.begin(); itr != m_attackers.end(); ++itr)
{
- if ((*itr) && !CanCreatureAttack(*itr) && (*itr)->GetTypeId() != TYPEID_PLAYER
+ if ((*itr) && CanCreatureAttack(*itr) && (*itr)->GetTypeId() != TYPEID_PLAYER
&& !(*itr)->ToCreature()->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN))
return nullptr;
}
@@ -11407,6 +11406,27 @@ void Unit::StopMoving()
init.Stop();
}
+void Unit::PauseMovement(uint32 timer/* = 0*/, uint8 slot/* = 0*/, bool forced/* = true*/)
+{
+ if (slot >= MAX_MOTION_SLOT)
+ return;
+
+ if (MovementGenerator* movementGenerator = GetMotionMaster()->GetMotionSlot(MovementSlot(slot)))
+ movementGenerator->Pause(timer);
+
+ if (forced)
+ StopMoving();
+}
+
+void Unit::ResumeMovement(uint32 timer/* = 0*/, uint8 slot/* = 0*/)
+{
+ if (slot >= MAX_MOTION_SLOT)
+ return;
+
+ if (MovementGenerator* movementGenerator = GetMotionMaster()->GetMotionSlot(MovementSlot(slot)))
+ movementGenerator->Resume(timer);
+}
+
void Unit::SendMovementFlagUpdate(bool self /* = false */)
{
WorldPacket data;
@@ -12597,8 +12617,14 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
if (GetTypeId() == TYPEID_UNIT)
{
+ if (MovementGenerator* movementGenerator = GetMotionMaster()->GetMotionSlot(MOTION_SLOT_IDLE))
+ movementGenerator->Pause(0);
+
+ GetMotionMaster()->Clear(MOTION_SLOT_ACTIVE);
+
+ StopMoving();
+
ToCreature()->AI()->OnCharmed(true);
- GetMotionMaster()->MoveIdle();
}
else if (Player* player = ToPlayer())
{
@@ -12712,6 +12738,7 @@ void Unit::RemoveCharmedBy(Unit* charmer)
else
RestoreFaction();
+ ///@todo Handle SLOT_IDLE motion resume
GetMotionMaster()->InitDefault();
if (Creature* creature = ToCreature())
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 4fc9a43e464..cfe2f840915 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1279,7 +1279,9 @@ class TC_GAME_API Unit : public WorldObject
void CastSpell(SpellCastTargets const& targets, SpellInfo const* spellInfo, CustomSpellValues const* value, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
void CastSpell(Unit* victim, uint32 spellId, bool triggered, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
+ void CastSpell(std::nullptr_t, uint32 spellId, bool triggered, Item* castItem = nullptr, AuraEffect* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty) { CastSpell((Unit*)nullptr, spellId, triggered, castItem, triggeredByAura, originalCaster); }
void CastSpell(Unit* victim, uint32 spellId, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
+ void CastSpell(std::nullptr_t, uint32 spellId, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty) { CastSpell((Unit*)nullptr, spellId, triggerFlags, castItem, triggeredByAura, originalCaster); }
void CastSpell(Unit* victim, SpellInfo const* spellInfo, bool triggered, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
void CastSpell(Unit* victim, SpellInfo const* spellInfo, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
void CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
@@ -1792,6 +1794,8 @@ class TC_GAME_API Unit : public WorldObject
bool IsStopped() const { return !(HasUnitState(UNIT_STATE_MOVING)); }
void StopMoving();
+ void PauseMovement(uint32 timer = 0, uint8 slot = 0, bool forced = true); // timer in ms
+ void ResumeMovement(uint32 timer = 0, uint8 slot = 0); // timer in ms
void AddUnitMovementFlag(uint32 f) { m_movementInfo.flags |= f; }
void RemoveUnitMovementFlag(uint32 f) { m_movementInfo.flags &= ~f; }
diff --git a/src/server/game/Entities/Unit/UnitDefines.h b/src/server/game/Entities/Unit/UnitDefines.h
index 47f0ed28923..04d3521e40c 100644
--- a/src/server/game/Entities/Unit/UnitDefines.h
+++ b/src/server/game/Entities/Unit/UnitDefines.h
@@ -131,7 +131,7 @@ enum UnitFlags : uint32
UNIT_FLAG_IMMUNE_TO_PC = 0x00000100, // disables combat/assistance with PlayerCharacters (PC) - see Unit::_IsValidAttackTarget, Unit::_IsValidAssistTarget
UNIT_FLAG_IMMUNE_TO_NPC = 0x00000200, // disables combat/assistance with NonPlayerCharacters (NPC) - see Unit::_IsValidAttackTarget, Unit::_IsValidAssistTarget
UNIT_FLAG_LOOTING = 0x00000400, // loot animation
- UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // in combat?, 2.0.8
+ UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // on player pets: whether the pet is chasing a target to attack || on other units: whether any of the unit's minions is in combat
UNIT_FLAG_PVP = 0x00001000, // changed in 3.0.3
UNIT_FLAG_SILENCED = 0x00002000, // silenced, 2.1.1
UNIT_FLAG_CANNOT_SWIM = 0x00004000, // 2.0.8
diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp
index 357cceb99b6..8b259438efc 100755
--- a/src/server/game/Entities/Vehicle/Vehicle.cpp
+++ b/src/server/game/Entities/Vehicle/Vehicle.cpp
@@ -148,7 +148,8 @@ void Vehicle::Reset(bool evading /*= false*/)
TC_LOG_DEBUG("entities.vehicle", "Vehicle::Reset (Entry: %u, GuidLow: %u, DBGuid: %u)", GetCreatureEntry(), _me->GetGUID().GetCounter(), _me->ToCreature()->GetSpawnId());
ApplyAllImmunities();
- InstallAllAccessories(evading);
+ if (GetBase()->IsAlive())
+ InstallAllAccessories(evading);
sScriptMgr->OnReset(this);
}
@@ -401,7 +402,7 @@ void Vehicle::InstallAccessory(uint32 entry, int8 seatId, bool minion, uint8 typ
* @author Machiavelli
* @date 17-2-2013
*
- * @param [in, out] The prospective passenger.
+ * @param unit The prospective passenger.
* @param seatId Identifier for the seat. Value of -1 indicates the next available seat.
*
* @return true if it succeeds, false if it fails.
@@ -772,6 +773,13 @@ bool VehicleJoinEvent::Execute(uint64, uint32)
Target->RemovePendingEventsForSeat(Seat->first);
Target->RemovePendingEventsForPassenger(Passenger);
+ // Passenger might've died in the meantime - abort if this is the case
+ if (!Passenger->IsAlive())
+ {
+ Abort(0);
+ return true;
+ }
+
Passenger->SetVehicle(Target);
Seat->second.Passenger.Guid = Passenger->GetGUID();
Seat->second.Passenger.IsUnselectable = Passenger->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp
index fc00ce5ee9e..14fdccce85e 100644
--- a/src/server/game/Events/GameEventMgr.cpp
+++ b/src/server/game/Events/GameEventMgr.cpp
@@ -218,12 +218,12 @@ void GameEventMgr::LoadFromDB()
{
{
uint32 oldMSTime = getMSTime();
- // 0 1 2 3 4 5 6 7 8
- QueryResult result = WorldDatabase.Query("SELECT eventEntry, UNIX_TIMESTAMP(start_time), UNIX_TIMESTAMP(end_time), occurence, length, holiday, description, world_event, announce FROM game_event");
+ // 0 1 2 3 4 5 6 7 8 9
+ QueryResult result = WorldDatabase.Query("SELECT eventEntry, UNIX_TIMESTAMP(start_time), UNIX_TIMESTAMP(end_time), occurence, length, holiday, holidayStage, description, world_event, announce FROM game_event");
if (!result)
{
mGameEvent.clear();
- TC_LOG_ERROR("server.loading", ">> Loaded 0 game events. DB table `game_event` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 game events. DB table `game_event` is empty.");
return;
}
@@ -247,10 +247,13 @@ void GameEventMgr::LoadFromDB()
pGameEvent.occurence = fields[3].GetUInt64();
pGameEvent.length = fields[4].GetUInt64();
pGameEvent.holiday_id = HolidayIds(fields[5].GetUInt32());
-
- pGameEvent.state = (GameEventState)(fields[7].GetUInt8());
+ pGameEvent.holidayStage = fields[6].GetUInt8();
+ pGameEvent.description = fields[7].GetString();
+ pGameEvent.state = (GameEventState)(fields[8].GetUInt8());
+ pGameEvent.announce = fields[9].GetUInt8();
pGameEvent.nextstart = 0;
- pGameEvent.announce = fields[8].GetUInt8();
+
+ ++count;
if (pGameEvent.length == 0 && pGameEvent.state == GAMEEVENT_NORMAL) // length>0 is validity check
{
@@ -264,12 +267,18 @@ void GameEventMgr::LoadFromDB()
{
TC_LOG_ERROR("sql.sql", "`game_event`: game event id (%i) contains nonexisting holiday id %u.", event_id, pGameEvent.holiday_id);
pGameEvent.holiday_id = HOLIDAY_NONE;
+ continue;
+ }
+ if (pGameEvent.holidayStage > MAX_HOLIDAY_DURATIONS)
+ {
+ TC_LOG_ERROR("sql.sql", "`game_event` game event id (%i) has out of range holidayStage %u.", event_id, pGameEvent.holidayStage);
+ pGameEvent.holidayStage = 0;
+ continue;
}
- }
- pGameEvent.description = fields[6].GetString();
+ SetHolidayEventTime(pGameEvent);
+ }
- ++count;
}
while (result->NextRow());
@@ -436,7 +445,7 @@ void GameEventMgr::LoadFromDB()
int32 internal_event_id = mGameEvent.size() + event_id - 1;
- GameObjectData const* data = sObjectMgr->GetGOData(guid);
+ GameObjectData const* data = sObjectMgr->GetGameObjectData(guid);
if (!data)
{
TC_LOG_ERROR("sql.sql", "`game_event_gameobject` contains gameobject (GUID: %u) not found in `gameobject` table.", guid);
@@ -929,6 +938,45 @@ void GameEventMgr::LoadFromDB()
}
}
+void GameEventMgr::LoadHolidayDates()
+{
+ uint32 oldMSTime = getMSTime();
+
+ // 0 1 2
+ QueryResult result = WorldDatabase.Query("SELECT id, date_id, date_value FROM holiday_dates");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 holiday dates. DB table `holiday_dates` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 holidayId = fields[0].GetUInt32();
+ HolidaysEntry* entry = const_cast<HolidaysEntry*>(sHolidaysStore.LookupEntry(holidayId));
+ if (!entry)
+ {
+ TC_LOG_ERROR("sql.sql", "holiday_dates entry has invalid holiday id %u.", holidayId);
+ continue;
+ }
+ uint8 dateId = fields[1].GetUInt8();
+ if (dateId >= MAX_HOLIDAY_DATES)
+ {
+ TC_LOG_ERROR("sql.sql", "holiday_dates entry has out of range date_id %u.", dateId);
+ continue;
+ }
+ entry->Date[dateId] = fields[2].GetUInt32();
+ modifiedHolidays.insert(entry->Id);
+ ++count;
+
+ } while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u holiday dates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
uint32 GameEventMgr::GetNPCFlag(Creature* cr)
{
uint32 mask = 0;
@@ -1140,7 +1188,7 @@ void GameEventMgr::UpdateEventNPCFlags(uint16 event_id)
for (NPCFlagList::iterator itr = mGameEventNPCFlags[event_id].begin(); itr != mGameEventNPCFlags[event_id].end(); ++itr)
// get the creature data from the low guid to get the entry, to be able to find out the whole guid
if (CreatureData const* data = sObjectMgr->GetCreatureData(itr->first))
- creaturesByMap[data->mapid].insert(itr->first);
+ creaturesByMap[data->spawnPoint.GetMapId()].insert(itr->first);
for (auto const& p : creaturesByMap)
{
@@ -1203,13 +1251,13 @@ void GameEventMgr::GameEventSpawn(int16 event_id)
sObjectMgr->AddCreatureToGrid(*itr, data);
// Spawn if necessary (loaded grids only)
- Map* map = sMapMgr->CreateBaseMap(data->mapid);
+ Map* map = sMapMgr->CreateBaseMap(data->spawnPoint.GetMapId());
// We use spawn coords to spawn
- if (!map->Instanceable() && map->IsGridLoaded(data->posX, data->posY))
+ if (!map->Instanceable() && map->IsGridLoaded(data->spawnPoint))
{
Creature* creature = new Creature();
//TC_LOG_DEBUG("misc", "Spawning creature %u", *itr);
- if (!creature->LoadCreatureFromDB(*itr, map))
+ if (!creature->LoadFromDB(*itr, map, true, false))
delete creature;
}
}
@@ -1225,19 +1273,19 @@ void GameEventMgr::GameEventSpawn(int16 event_id)
for (GuidList::iterator itr = mGameEventGameobjectGuids[internal_event_id].begin(); itr != mGameEventGameobjectGuids[internal_event_id].end(); ++itr)
{
// Add to correct cell
- if (GameObjectData const* data = sObjectMgr->GetGOData(*itr))
+ if (GameObjectData const* data = sObjectMgr->GetGameObjectData(*itr))
{
sObjectMgr->AddGameobjectToGrid(*itr, data);
// Spawn if necessary (loaded grids only)
// this base map checked as non-instanced and then only existed
- Map* map = sMapMgr->CreateBaseMap(data->mapid);
+ Map* map = sMapMgr->CreateBaseMap(data->spawnPoint.GetMapId());
// We use current coords to unspawn, not spawn coords since creature can have changed grid
- if (!map->Instanceable() && map->IsGridLoaded(data->posX, data->posY))
+ if (!map->Instanceable() && map->IsGridLoaded(data->spawnPoint))
{
GameObject* pGameobject = new GameObject;
//TC_LOG_DEBUG("misc", "Spawning gameobject %u", *itr);
/// @todo find out when it is add to map
- if (!pGameobject->LoadGameObjectFromDB(*itr, map, false))
+ if (!pGameobject->LoadFromDB(*itr, map, false))
delete pGameobject;
else
{
@@ -1280,7 +1328,7 @@ void GameEventMgr::GameEventUnspawn(int16 event_id)
{
sObjectMgr->RemoveCreatureFromGrid(*itr, data);
- sMapMgr->DoForAllMapsWithMapId(data->mapid, [&itr](Map* map)
+ sMapMgr->DoForAllMapsWithMapId(data->spawnPoint.GetMapId(), [&itr](Map* map)
{
auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(*itr);
for (auto itr2 = creatureBounds.first; itr2 != creatureBounds.second;)
@@ -1306,11 +1354,11 @@ void GameEventMgr::GameEventUnspawn(int16 event_id)
if (event_id >0 && hasGameObjectActiveEventExcept(*itr, event_id))
continue;
// Remove the gameobject from grid
- if (GameObjectData const* data = sObjectMgr->GetGOData(*itr))
+ if (GameObjectData const* data = sObjectMgr->GetGameObjectData(*itr))
{
sObjectMgr->RemoveGameobjectFromGrid(*itr, data);
- sMapMgr->DoForAllMapsWithMapId(data->mapid, [&itr](Map* map)
+ sMapMgr->DoForAllMapsWithMapId(data->spawnPoint.GetMapId(), [&itr](Map* map)
{
auto gameobjectBounds = map->GetGameObjectBySpawnIdStore().equal_range(*itr);
for (auto itr2 = gameobjectBounds.first; itr2 != gameobjectBounds.second;)
@@ -1344,7 +1392,7 @@ void GameEventMgr::ChangeEquipOrModel(int16 event_id, bool activate)
continue;
// Update if spawned
- sMapMgr->DoForAllMapsWithMapId(data->mapid, [&itr, activate](Map* map)
+ sMapMgr->DoForAllMapsWithMapId(data->spawnPoint.GetMapId(), [&itr, activate](Map* map)
{
auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(itr->first);
@@ -1667,6 +1715,84 @@ void GameEventMgr::RunSmartAIScripts(uint16 event_id, bool activate)
});
}
+void GameEventMgr::SetHolidayEventTime(GameEventData& event)
+{
+ if (!event.holidayStage) // Ignore holiday
+ return;
+
+ const HolidaysEntry* holiday = sHolidaysStore.LookupEntry(event.holiday_id);
+
+ if (!holiday->Date[0] || !holiday->Duration[0]) // Invalid definitions
+ {
+ TC_LOG_ERROR("sql.sql", "Missing date or duration for holiday %u.", event.holiday_id);
+ return;
+ }
+
+ uint8 stageIndex = event.holidayStage - 1;
+ event.length = holiday->Duration[stageIndex] * HOUR / MINUTE;
+
+ time_t stageOffset = 0;
+ for (int i = 0; i < stageIndex; ++i)
+ stageOffset += holiday->Duration[i] * HOUR;
+
+ switch (holiday->CalendarFilterType)
+ {
+ case -1: // Yearly
+ event.occurence = YEAR / MINUTE; // Not all too useful
+ break;
+ case 0: // Weekly
+ event.occurence = WEEK / MINUTE;
+ break;
+ case 1: // Defined dates only (Darkmoon Faire)
+ break;
+ case 2: // Only used for looping events (Call to Arms)
+ break;
+ }
+
+ if (holiday->Looping)
+ {
+ event.occurence = 0;
+ for (int i = 0; i < MAX_HOLIDAY_DURATIONS && holiday->Duration[i]; ++i)
+ event.occurence += holiday->Duration[i] * HOUR / MINUTE;
+ }
+
+ bool singleDate = ((holiday->Date[0] >> 24) & 0x1F) == 31; // Events with fixed date within year have - 1
+
+ time_t curTime = time(NULL);
+ for (int i = 0; i < MAX_HOLIDAY_DATES && holiday->Date[i]; ++i)
+ {
+ uint32 date = holiday->Date[i];
+
+ tm timeInfo;
+ if (singleDate)
+ timeInfo.tm_year = localtime(&curTime)->tm_year - 1; // First try last year (event active through New Year)
+ else
+ timeInfo.tm_year = ((date >> 24) & 0x1F) + 100;
+
+ timeInfo.tm_mon = (date >> 20) & 0xF;
+ timeInfo.tm_mday = ((date >> 14) & 0x3F) + 1;
+ timeInfo.tm_hour = (date >> 6) & 0x1F;
+ timeInfo.tm_min = date & 0x3F;
+ timeInfo.tm_sec = 0;
+ timeInfo.tm_isdst = -1;
+ tm tmCopy = timeInfo;
+
+ time_t startTime = mktime(&timeInfo);
+ if (curTime < startTime + event.length * MINUTE)
+ {
+ event.start = startTime + stageOffset;
+ return;
+ }
+ else if (singleDate)
+ {
+ tmCopy.tm_year = localtime(&curTime)->tm_year; // This year
+ event.start = mktime(&tmCopy) + stageOffset;
+ return;
+ }
+ }
+ TC_LOG_ERROR("sql.sql", "No suitable start date found for holiday %u.", event.holiday_id);
+}
+
bool IsHolidayActive(HolidayIds id)
{
if (id == HOLIDAY_NONE)
diff --git a/src/server/game/Events/GameEventMgr.h b/src/server/game/Events/GameEventMgr.h
index bee6dfc8fb3..4d1ce718422 100644
--- a/src/server/game/Events/GameEventMgr.h
+++ b/src/server/game/Events/GameEventMgr.h
@@ -60,7 +60,7 @@ typedef std::map<uint32 /*condition id*/, GameEventFinishCondition> GameEventCon
struct GameEventData
{
- GameEventData() : start(1), end(0), nextstart(0), occurence(0), length(0), holiday_id(HOLIDAY_NONE), state(GAMEEVENT_NORMAL),
+ GameEventData() : start(1), end(0), nextstart(0), occurence(0), length(0), holiday_id(HOLIDAY_NONE), holidayStage(0), state(GAMEEVENT_NORMAL),
announce(0) { }
time_t start; // occurs after this time
time_t end; // occurs before this time
@@ -68,6 +68,7 @@ struct GameEventData
uint32 occurence; // time between end and start
uint32 length; // length of the event (minutes) after finishing all conditions
HolidayIds holiday_id;
+ uint8 holidayStage;
GameEventState state; // state of the game event, these are saved into the game_event table on change!
GameEventConditionMap conditions; // conditions to finish
std::set<uint16 /*gameevent id*/> prerequisite_events; // events that must be completed before starting this event
@@ -114,6 +115,7 @@ class TC_GAME_API GameEventMgr
bool CheckOneGameEvent(uint16 entry) const;
uint32 NextCheck(uint16 entry) const;
void LoadFromDB();
+ void LoadHolidayDates();
uint32 Update();
bool IsActiveEvent(uint16 event_id) { return (m_ActiveEvents.find(event_id) != m_ActiveEvents.end()); }
uint32 StartSystem();
@@ -147,6 +149,7 @@ class TC_GAME_API GameEventMgr
bool hasGameObjectQuestActiveEventExcept(uint32 quest_id, uint16 event_id);
bool hasCreatureActiveEventExcept(ObjectGuid::LowType creature_guid, uint16 event_id);
bool hasGameObjectActiveEventExcept(ObjectGuid::LowType go_guid, uint16 event_id);
+ void SetHolidayEventTime(GameEventData& event);
typedef std::list<ObjectGuid::LowType> GuidList;
typedef std::list<uint32> IdList;
@@ -181,6 +184,7 @@ class TC_GAME_API GameEventMgr
public:
GameEventGuidMap mGameEventCreatureGuids;
GameEventGuidMap mGameEventGameobjectGuids;
+ std::set<uint32> modifiedHolidays;
};
#define sGameEventMgr GameEventMgr::instance()
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 1b7713ab363..2f1e4fa48f3 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -30,6 +30,7 @@
#include "GroupMgr.h"
#include "GuildMgr.h"
#include "InstanceSaveMgr.h"
+#include "InstanceScript.h"
#include "Language.h"
#include "LFGMgr.h"
#include "Log.h"
@@ -831,7 +832,7 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) lists non-existing Modelid1 id (%u), this can crash the client.", cInfo->Entry, cInfo->Modelid1);
const_cast<CreatureTemplate*>(cInfo)->Modelid1 = 0;
}
- else if (!displayScaleEntry)
+ else
displayScaleEntry = displayEntry;
CreatureModelInfo const* modelInfo = GetCreatureModelInfo(cInfo->Modelid1);
@@ -1123,7 +1124,7 @@ void ObjectMgr::LoadGameObjectAddons()
ObjectGuid::LowType guid = fields[0].GetUInt32();
- GameObjectData const* goData = GetGOData(guid);
+ GameObjectData const* goData = GetGameObjectData(guid);
if (!goData)
{
TC_LOG_ERROR("sql.sql", "GameObject (GUID: %u) does not exist but has a record in `gameobject_addon`", guid);
@@ -1427,7 +1428,7 @@ void ObjectMgr::LoadLinkedRespawn()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 linked respawns. DB table `linked_respawn` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 linked respawns. DB table `linked_respawn` is empty.");
return;
}
@@ -1461,8 +1462,8 @@ void ObjectMgr::LoadLinkedRespawn()
break;
}
- MapEntry const* const map = sMapStore.LookupEntry(master->mapid);
- if (!map || !map->Instanceable() || (master->mapid != slave->mapid))
+ MapEntry const* const map = sMapStore.LookupEntry(master->spawnPoint.GetMapId());
+ if (!map || !map->Instanceable() || (master->spawnPoint.GetMapId() != slave->spawnPoint.GetMapId()))
{
TC_LOG_ERROR("sql.sql", "LinkedRespawn: Creature '%u' linking to Creature '%u' on an unpermitted map.", guidLow, linkedGuidLow);
error = true;
@@ -1490,7 +1491,7 @@ void ObjectMgr::LoadLinkedRespawn()
break;
}
- GameObjectData const* master = GetGOData(linkedGuidLow);
+ GameObjectData const* master = GetGameObjectData(linkedGuidLow);
if (!master)
{
TC_LOG_ERROR("sql.sql", "LinkedRespawn: Gameobject (linkedGuid) '%u' not found in gameobject table", linkedGuidLow);
@@ -1498,8 +1499,8 @@ void ObjectMgr::LoadLinkedRespawn()
break;
}
- MapEntry const* const map = sMapStore.LookupEntry(master->mapid);
- if (!map || !map->Instanceable() || (master->mapid != slave->mapid))
+ MapEntry const* const map = sMapStore.LookupEntry(master->spawnPoint.GetMapId());
+ if (!map || !map->Instanceable() || (master->spawnPoint.GetMapId() != slave->spawnPoint.GetMapId()))
{
TC_LOG_ERROR("sql.sql", "LinkedRespawn: Creature '%u' linking to Gameobject '%u' on an unpermitted map.", guidLow, linkedGuidLow);
error = true;
@@ -1519,7 +1520,7 @@ void ObjectMgr::LoadLinkedRespawn()
}
case GO_TO_GO:
{
- GameObjectData const* slave = GetGOData(guidLow);
+ GameObjectData const* slave = GetGameObjectData(guidLow);
if (!slave)
{
TC_LOG_ERROR("sql.sql", "LinkedRespawn: Gameobject (guid) '%u' not found in gameobject table", guidLow);
@@ -1527,7 +1528,7 @@ void ObjectMgr::LoadLinkedRespawn()
break;
}
- GameObjectData const* master = GetGOData(linkedGuidLow);
+ GameObjectData const* master = GetGameObjectData(linkedGuidLow);
if (!master)
{
TC_LOG_ERROR("sql.sql", "LinkedRespawn: Gameobject (linkedGuid) '%u' not found in gameobject table", linkedGuidLow);
@@ -1535,8 +1536,8 @@ void ObjectMgr::LoadLinkedRespawn()
break;
}
- MapEntry const* const map = sMapStore.LookupEntry(master->mapid);
- if (!map || !map->Instanceable() || (master->mapid != slave->mapid))
+ MapEntry const* const map = sMapStore.LookupEntry(master->spawnPoint.GetMapId());
+ if (!map || !map->Instanceable() || (master->spawnPoint.GetMapId() != slave->spawnPoint.GetMapId()))
{
TC_LOG_ERROR("sql.sql", "LinkedRespawn: Gameobject '%u' linking to Gameobject '%u' on an unpermitted map.", guidLow, linkedGuidLow);
error = true;
@@ -1556,7 +1557,7 @@ void ObjectMgr::LoadLinkedRespawn()
}
case GO_TO_CREATURE:
{
- GameObjectData const* slave = GetGOData(guidLow);
+ GameObjectData const* slave = GetGameObjectData(guidLow);
if (!slave)
{
TC_LOG_ERROR("sql.sql", "LinkedRespawn: Gameobject (guid) '%u' not found in gameobject table", guidLow);
@@ -1572,8 +1573,8 @@ void ObjectMgr::LoadLinkedRespawn()
break;
}
- MapEntry const* const map = sMapStore.LookupEntry(master->mapid);
- if (!map || !map->Instanceable() || (master->mapid != slave->mapid))
+ MapEntry const* const map = sMapStore.LookupEntry(master->spawnPoint.GetMapId());
+ if (!map || !map->Instanceable() || (master->spawnPoint.GetMapId() != slave->spawnPoint.GetMapId()))
{
TC_LOG_ERROR("sql.sql", "LinkedRespawn: Gameobject '%u' linking to Creature '%u' on an unpermitted map.", guidLow, linkedGuidLow);
error = true;
@@ -1626,8 +1627,8 @@ bool ObjectMgr::SetCreatureLinkedRespawn(ObjectGuid::LowType guidLow, ObjectGuid
return false;
}
- MapEntry const* map = sMapStore.LookupEntry(master->mapid);
- if (!map || !map->Instanceable() || (master->mapid != slave->mapid))
+ MapEntry const* map = sMapStore.LookupEntry(master->spawnPoint.GetMapId());
+ if (!map || !map->Instanceable() || (master->spawnPoint.GetMapId() != slave->spawnPoint.GetMapId()))
{
TC_LOG_ERROR("sql.sql", "Creature '%u' linking to '%u' on an unpermitted map.", guidLow, linkedGuidLow);
return false;
@@ -1741,8 +1742,8 @@ void ObjectMgr::LoadCreatures()
{
uint32 oldMSTime = getMSTime();
- // 0 1 2 3 4 5 6 7 8 9 10
- QueryResult result = WorldDatabase.Query("SELECT creature.guid, id, map, modelid, equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, spawndist, "
+ // 0 1 2 3 4 5 6 7 8 9 10
+ QueryResult result = WorldDatabase.Query("SELECT creature.guid, id, map, position_x, position_y, position_z, orientation, modelid, equipment_id, spawntimesecs, spawndist, "
// 11 12 13 14 15 16 17 18 19 20 21
"currentwaypoint, curhealth, curmana, MovementType, spawnMask, phaseMask, eventEntry, pool_entry, creature.npcflag, creature.unit_flags, creature.dynamicflags, "
// 22
@@ -1753,7 +1754,7 @@ void ObjectMgr::LoadCreatures()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 creatures. DB table `creature` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 creatures. DB table `creature` is empty.");
return;
}
@@ -1782,14 +1783,11 @@ void ObjectMgr::LoadCreatures()
}
CreatureData& data = _creatureDataStore[guid];
+ data.spawnId = guid;
data.id = entry;
- data.mapid = fields[2].GetUInt16();
- data.displayid = fields[3].GetUInt32();
- data.equipmentId = fields[4].GetInt8();
- data.posX = fields[5].GetFloat();
- data.posY = fields[6].GetFloat();
- data.posZ = fields[7].GetFloat();
- data.orientation = fields[8].GetFloat();
+ data.spawnPoint.WorldRelocate(fields[2].GetUInt16(), fields[3].GetFloat(), fields[4].GetFloat(), fields[5].GetFloat(), fields[6].GetFloat());
+ data.displayid = fields[7].GetUInt32();
+ data.equipmentId = fields[8].GetInt8();
data.spawntimesecs = fields[9].GetUInt32();
data.spawndist = fields[10].GetFloat();
data.currentwaypoint= fields[11].GetUInt32();
@@ -1803,18 +1801,19 @@ void ObjectMgr::LoadCreatures()
data.npcflag = fields[19].GetUInt32();
data.unit_flags = fields[20].GetUInt32();
data.dynamicflags = fields[21].GetUInt32();
- data.ScriptId = GetScriptId(fields[22].GetString());
+ data.scriptId = GetScriptId(fields[22].GetString());
+ data.spawnGroupData = &_spawnGroupDataStore[0];
- MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapid);
+ MapEntry const* mapEntry = sMapStore.LookupEntry(data.spawnPoint.GetMapId());
if (!mapEntry)
{
- TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: %u) that spawned at nonexistent map (Id: %u), skipped.", guid, data.mapid);
+ TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: %u) that spawned at nonexistent map (Id: %u), skipped.", guid, data.spawnPoint.GetMapId());
continue;
}
// Skip spawnMask check for transport maps
- if (!IsTransportMap(data.mapid) && data.spawnMask & ~spawnMasks[data.mapid])
- TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: %u) that have wrong spawn mask %u including unsupported difficulty modes for map (Id: %u).", guid, data.spawnMask, data.mapid);
+ if (!IsTransportMap(data.spawnPoint.GetMapId()) && data.spawnMask & ~spawnMasks[data.spawnPoint.GetMapId()])
+ TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: %u) that have wrong spawn mask %u including unsupported difficulty modes for map (Id: %u).", guid, data.spawnMask, data.spawnPoint.GetMapId());
bool ok = true;
for (uint32 diff = 0; diff < MAX_DIFFICULTY - 1 && ok; ++diff)
@@ -1879,17 +1878,11 @@ void ObjectMgr::LoadCreatures()
data.phaseMask = 1;
}
- if (std::abs(data.orientation) > 2 * float(M_PI))
- {
- TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: %u Entry: %u) with abs(`orientation`) > 2*PI (orientation is expressed in radians), normalized.", guid, data.id);
- data.orientation = Position::NormalizeOrientation(data.orientation);
- }
-
if (sWorld->getBoolConfig(CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA))
{
uint32 zoneId = 0;
uint32 areaId = 0;
- sMapMgr->GetZoneAndAreaId(zoneId, areaId, data.mapid, data.posX, data.posY, data.posZ);
+ sMapMgr->GetZoneAndAreaId(zoneId, areaId, data.spawnPoint);
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_ZONE_AREA_DATA);
@@ -1916,8 +1909,8 @@ void ObjectMgr::AddCreatureToGrid(ObjectGuid::LowType guid, CreatureData const*
{
if (mask & 1)
{
- CellCoord cellCoord = Trinity::ComputeCellCoord(data->posX, data->posY);
- CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()];
+ CellCoord cellCoord = Trinity::ComputeCellCoord(data->spawnPoint.GetPositionX(), data->spawnPoint.GetPositionY());
+ CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->spawnPoint.GetMapId(), i)][cellCoord.GetId()];
cell_guids.creatures.insert(guid);
}
}
@@ -1930,14 +1923,14 @@ void ObjectMgr::RemoveCreatureFromGrid(ObjectGuid::LowType guid, CreatureData co
{
if (mask & 1)
{
- CellCoord cellCoord = Trinity::ComputeCellCoord(data->posX, data->posY);
- CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()];
+ CellCoord cellCoord = Trinity::ComputeCellCoord(data->spawnPoint.GetPositionX(), data->spawnPoint.GetPositionY());
+ CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->spawnPoint.GetMapId(), i)][cellCoord.GetId()];
cell_guids.creatures.erase(guid);
}
}
}
-ObjectGuid::LowType ObjectMgr::AddGOData(uint32 entry, uint32 mapId, Position const& pos, QuaternionData const& rot, uint32 spawntimedelay /*= 0*/)
+ObjectGuid::LowType ObjectMgr::AddGameObjectData(uint32 entry, uint32 mapId, Position const& pos, QuaternionData const& rot, uint32 spawntimedelay /*= 0*/)
{
GameObjectTemplate const* goinfo = GetGameObjectTemplate(entry);
if (!goinfo)
@@ -1947,41 +1940,40 @@ ObjectGuid::LowType ObjectMgr::AddGOData(uint32 entry, uint32 mapId, Position co
if (!map)
return 0;
- ObjectGuid::LowType guid = GenerateGameObjectSpawnId();
+ ObjectGuid::LowType spawnId = GenerateGameObjectSpawnId();
- GameObjectData& data = NewGOData(guid);
+ GameObjectData& data = NewOrExistGameObjectData(spawnId);
+ data.spawnId = spawnId;
data.id = entry;
- data.mapid = mapId;
-
- pos.GetPosition(data.posX, data.posY, data.posZ, data.orientation);
-
+ data.spawnPoint.WorldRelocate(mapId,pos);
data.rotation = rot;
data.spawntimesecs = spawntimedelay;
data.animprogress = 100;
data.spawnMask = 1;
- data.go_state = GO_STATE_READY;
+ data.goState = GO_STATE_READY;
data.phaseMask = PHASEMASK_NORMAL;
data.artKit = goinfo->type == GAMEOBJECT_TYPE_CAPTURE_POINT ? 21 : 0;
- data.dbData = false;
+ data.dbData = false;
+ data.spawnGroupData = GetLegacySpawnGroup();
- AddGameobjectToGrid(guid, &data);
+ AddGameobjectToGrid(spawnId, &data);
// Spawn if necessary (loaded grids only)
// We use spawn coords to spawn
- if (!map->Instanceable() && map->IsGridLoaded(data.posX, data.posY))
+ if (!map->Instanceable() && map->IsGridLoaded(data.spawnPoint))
{
GameObject* go = new GameObject;
- if (!go->LoadGameObjectFromDB(guid, map))
+ if (!go->LoadFromDB(spawnId, map, true))
{
- TC_LOG_ERROR("misc", "AddGOData: cannot add gameobject entry %u to map", entry);
+ TC_LOG_ERROR("misc", "AddGameObjectData: cannot add gameobject entry %u to map", entry);
delete go;
return 0;
}
}
- TC_LOG_DEBUG("maps", "AddGOData: dbguid %u entry %u map %u x %f y %f z %f o %f", guid, entry, mapId, data.posX, data.posY, data.posZ, data.orientation);
+ TC_LOG_DEBUG("maps", "AddGameObjectData: dbguid %u entry %u map %u pos %s", spawnId, entry, mapId, data.spawnPoint.ToString().c_str());
- return guid;
+ return spawnId;
}
@@ -1997,15 +1989,13 @@ ObjectGuid::LowType ObjectMgr::AddCreatureData(uint32 entry, uint32 mapId, Posit
if (!map)
return 0;
- ObjectGuid::LowType guid = GenerateCreatureSpawnId();
- CreatureData& data = NewOrExistCreatureData(guid);
+ ObjectGuid::LowType spawnId = GenerateCreatureSpawnId();
+ CreatureData& data = NewOrExistCreatureData(spawnId);
+ data.spawnId = spawnId;
data.id = entry;
- data.mapid = mapId;
+ data.spawnPoint.WorldRelocate(mapId, pos);
data.displayid = 0;
data.equipmentId = 0;
-
- pos.GetPosition(data.posX, data.posY, data.posZ, data.orientation);
-
data.spawntimesecs = spawntimedelay;
data.spawndist = 0;
data.currentwaypoint = 0;
@@ -2018,14 +2008,15 @@ ObjectGuid::LowType ObjectMgr::AddCreatureData(uint32 entry, uint32 mapId, Posit
data.npcflag = cInfo->npcflag;
data.unit_flags = cInfo->unit_flags;
data.dynamicflags = cInfo->dynamicflags;
+ data.spawnGroupData = GetLegacySpawnGroup();
- AddCreatureToGrid(guid, &data);
+ AddCreatureToGrid(spawnId, &data);
// We use spawn coords to spawn
- if (!map->Instanceable() && !map->IsRemovalGrid(data.posX, data.posY))
+ if (!map->Instanceable() && !map->IsRemovalGrid(data.spawnPoint))
{
Creature* creature = new Creature();
- if (!creature->LoadCreatureFromDB(guid, map))
+ if (!creature->LoadFromDB(spawnId, map, true, true))
{
TC_LOG_ERROR("misc", "AddCreature: Cannot add creature entry %u to map", entry);
delete creature;
@@ -2033,10 +2024,10 @@ ObjectGuid::LowType ObjectMgr::AddCreatureData(uint32 entry, uint32 mapId, Posit
}
}
- return guid;
+ return spawnId;
}
-void ObjectMgr::LoadGameobjects()
+void ObjectMgr::LoadGameObjects()
{
uint32 oldMSTime = getMSTime();
@@ -2051,7 +2042,7 @@ void ObjectMgr::LoadGameobjects()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 gameobjects. DB table `gameobject` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 gameobjects. DB table `gameobject` is empty.");
return;
}
@@ -2100,22 +2091,20 @@ void ObjectMgr::LoadGameobjects()
GameObjectData& data = _gameObjectDataStore[guid];
+ data.spawnId = guid;
data.id = entry;
- data.mapid = fields[2].GetUInt16();
- data.posX = fields[3].GetFloat();
- data.posY = fields[4].GetFloat();
- data.posZ = fields[5].GetFloat();
- data.orientation = fields[6].GetFloat();
+ data.spawnPoint.WorldRelocate(fields[2].GetUInt16(), fields[3].GetFloat(), fields[4].GetFloat(), fields[5].GetFloat(), fields[6].GetFloat());
data.rotation.x = fields[7].GetFloat();
data.rotation.y = fields[8].GetFloat();
data.rotation.z = fields[9].GetFloat();
data.rotation.w = fields[10].GetFloat();
data.spawntimesecs = fields[11].GetInt32();
+ data.spawnGroupData = &_spawnGroupDataStore[0];
- MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapid);
+ MapEntry const* mapEntry = sMapStore.LookupEntry(data.spawnPoint.GetMapId());
if (!mapEntry)
{
- TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: %u Entry: %u) spawned on a non-existed map (Id: %u), skip", guid, data.id, data.mapid);
+ TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: %u Entry: %u) spawned on a non-existed map (Id: %u), skip", guid, data.id, data.spawnPoint.GetMapId());
continue;
}
@@ -2133,24 +2122,18 @@ void ObjectMgr::LoadGameobjects()
TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: %u Entry: %u) with invalid `state` (%u) value, skip", guid, data.id, go_state);
continue;
}
- data.go_state = GOState(go_state);
+ data.goState = GOState(go_state);
data.spawnMask = fields[14].GetUInt8();
- if (!IsTransportMap(data.mapid) && data.spawnMask & ~spawnMasks[data.mapid])
- TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: %u Entry: %u) that has wrong spawn mask %u including unsupported difficulty modes for map (Id: %u), skip", guid, data.id, data.spawnMask, data.mapid);
+ if (!IsTransportMap(data.spawnPoint.GetMapId()) && data.spawnMask & ~spawnMasks[data.spawnPoint.GetMapId()])
+ TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: %u Entry: %u) that has wrong spawn mask %u including unsupported difficulty modes for map (Id: %u), skip", guid, data.id, data.spawnMask, data.spawnPoint.GetMapId());
data.phaseMask = fields[15].GetUInt32();
int16 gameEvent = fields[16].GetInt8();
uint32 PoolId = fields[17].GetUInt32();
- data.ScriptId = GetScriptId(fields[18].GetString());
-
- if (std::abs(data.orientation) > 2 * float(M_PI))
- {
- TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: %u Entry: %u) with abs(`orientation`) > 2*PI (orientation is expressed in radians), normalized.", guid, data.id);
- data.orientation = Position::NormalizeOrientation(data.orientation);
- }
+ data.scriptId = GetScriptId(fields[18].GetString());
if (data.rotation.x < -1.0f || data.rotation.x > 1.0f)
{
@@ -2176,7 +2159,7 @@ void ObjectMgr::LoadGameobjects()
continue;
}
- if (!MapManager::IsValidMapCoord(data.mapid, data.posX, data.posY, data.posZ, data.orientation))
+ if (!MapManager::IsValidMapCoord(data.spawnPoint))
{
TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: %u Entry: %u) with invalid coordinates, skip", guid, data.id);
continue;
@@ -2192,7 +2175,7 @@ void ObjectMgr::LoadGameobjects()
{
uint32 zoneId = 0;
uint32 areaId = 0;
- sMapMgr->GetZoneAndAreaId(zoneId, areaId, data.mapid, data.posX, data.posY, data.posZ);
+ sMapMgr->GetZoneAndAreaId(zoneId, areaId, data.spawnPoint);
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_GAMEOBJECT_ZONE_AREA_DATA);
@@ -2211,6 +2194,207 @@ void ObjectMgr::LoadGameobjects()
TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " gameobjects in %u ms", _gameObjectDataStore.size(), GetMSTimeDiffToNow(oldMSTime));
}
+void ObjectMgr::LoadSpawnGroupTemplates()
+{
+ uint32 oldMSTime = getMSTime();
+
+ // 0 1 2
+ QueryResult result = WorldDatabase.Query("SELECT groupId, groupName, groupFlags FROM spawn_group_template");
+
+ if (result)
+ {
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 groupId = fields[0].GetUInt32();
+ SpawnGroupTemplateData& group = _spawnGroupDataStore[groupId];
+ group.groupId = groupId;
+ group.name = fields[1].GetString();
+ group.mapId = SPAWNGROUP_MAP_UNSET;
+ uint32 flags = fields[2].GetUInt32();
+ if (flags & ~SPAWNGROUP_FLAGS_ALL)
+ {
+ flags &= SPAWNGROUP_FLAGS_ALL;
+ TC_LOG_ERROR("sql.sql", "Invalid spawn group flag %u on group ID %u (%s), reduced to valid flag %u.", flags, groupId, group.name.c_str(), uint32(group.flags));
+ }
+ if (flags & SPAWNGROUP_FLAG_SYSTEM && flags & SPAWNGROUP_FLAG_MANUAL_SPAWN)
+ {
+ flags &= ~SPAWNGROUP_FLAG_MANUAL_SPAWN;
+ TC_LOG_ERROR("sql.sql", "System spawn group %u (%s) has invalid manual spawn flag. Ignored.", groupId, group.name.c_str());
+ }
+ group.flags = SpawnGroupFlags(flags);
+ } while (result->NextRow());
+ }
+
+ if (_spawnGroupDataStore.find(0) == _spawnGroupDataStore.end())
+ {
+ TC_LOG_ERROR("sql.sql", "Default spawn group (index 0) is missing from DB! Manually inserted.");
+ SpawnGroupTemplateData& data = _spawnGroupDataStore[0];
+ data.groupId = 0;
+ data.name = "Default Group";
+ data.mapId = 0;
+ data.flags = SPAWNGROUP_FLAG_SYSTEM;
+ }
+ if (_spawnGroupDataStore.find(1) == _spawnGroupDataStore.end())
+ {
+ TC_LOG_ERROR("sql.sql", "Default legacy spawn group (index 1) is missing from DB! Manually inserted.");
+ SpawnGroupTemplateData&data = _spawnGroupDataStore[1];
+ data.groupId = 1;
+ data.name = "Legacy Group";
+ data.mapId = 0;
+ data.flags = SpawnGroupFlags(SPAWNGROUP_FLAG_SYSTEM | SPAWNGROUP_FLAG_COMPATIBILITY_MODE);
+ }
+
+ if (result)
+ TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " spawn group templates in %u ms", _spawnGroupDataStore.size(), GetMSTimeDiffToNow(oldMSTime));
+ else
+ TC_LOG_INFO("server.loading", ">> Loaded 0 spawn group templates. DB table `spawn_group_template` is empty.");
+
+ return;
+}
+
+void ObjectMgr::LoadSpawnGroups()
+{
+ uint32 oldMSTime = getMSTime();
+
+ // 0 1 2
+ QueryResult result = WorldDatabase.Query("SELECT groupId, spawnType, spawnId FROM spawn_group");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 spawn group members. DB table `spawn_group` is empty.");
+ return;
+ }
+
+ uint32 numMembers = 0;
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 groupId = fields[0].GetUInt32();
+ SpawnObjectType spawnType;
+ {
+ uint32 type = fields[1].GetUInt8();
+ if (type >= SPAWN_TYPE_MAX)
+ {
+ TC_LOG_ERROR("sql.sql", "Spawn data with invalid type %u listed for spawn group %u. Skipped.", type, groupId);
+ continue;
+ }
+ spawnType = SpawnObjectType(type);
+ }
+ ObjectGuid::LowType spawnId = fields[2].GetUInt32();
+
+ SpawnData const* data = GetSpawnData(spawnType, spawnId);
+ if (!data)
+ {
+ TC_LOG_ERROR("sql.sql", "Spawn data with ID (%u,%u) not found, but is listed as a member of spawn group %u!", uint32(spawnType), spawnId, groupId);
+ continue;
+ }
+ else if (data->spawnGroupData->groupId)
+ {
+ TC_LOG_ERROR("sql.sql", "Spawn with ID (%u,%u) is listed as a member of spawn group %u, but is already a member of spawn group %u. Skipping.", uint32(spawnType), spawnId, groupId, data->spawnGroupData->groupId);
+ continue;
+ }
+ auto it = _spawnGroupDataStore.find(groupId);
+ if (it == _spawnGroupDataStore.end())
+ {
+ TC_LOG_ERROR("sql.sql", "Spawn group %u assigned to spawn ID (%u,%u), but group is found!", groupId, uint32(spawnType), spawnId);
+ continue;
+ }
+ else
+ {
+ SpawnGroupTemplateData& groupTemplate = it->second;
+ if (groupTemplate.mapId == SPAWNGROUP_MAP_UNSET)
+ groupTemplate.mapId = data->spawnPoint.GetMapId();
+ else if (groupTemplate.mapId != data->spawnPoint.GetMapId() && !(groupTemplate.flags & SPAWNGROUP_FLAG_SYSTEM))
+ {
+ TC_LOG_ERROR("sql.sql", "Spawn group %u has map ID %u, but spawn (%u,%u) has map id %u - spawn NOT added to group!", groupId, groupTemplate.mapId, uint32(spawnType), spawnId, data->spawnPoint.GetMapId());
+ continue;
+ }
+ const_cast<SpawnData*>(data)->spawnGroupData = &groupTemplate;
+ if (!(groupTemplate.flags & SPAWNGROUP_FLAG_SYSTEM))
+ _spawnGroupMapStore.emplace(groupId, data);
+ ++numMembers;
+ }
+ } while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u spawn group members in %u ms", numMembers, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void ObjectMgr::LoadInstanceSpawnGroups()
+{
+ uint32 oldMSTime = getMSTime();
+
+ // 0 1 2 3 4
+ QueryResult result = WorldDatabase.Query("SELECT instanceMapId, bossStateId, bossStates, spawnGroupId, flags FROM instance_spawn_groups");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 instance spawn groups. DB table `instance_spawn_groups` is empty.");
+ return;
+ }
+
+ uint32 n = 0;
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 const spawnGroupId = fields[3].GetUInt32();
+ auto it = _spawnGroupDataStore.find(spawnGroupId);
+ if (it == _spawnGroupDataStore.end() || (it->second.flags & SPAWNGROUP_FLAG_SYSTEM))
+ {
+ TC_LOG_ERROR("sql.sql", "Invalid spawn group %u specified for instance %u. Skipped.", spawnGroupId, fields[0].GetUInt16());
+ continue;
+ }
+
+ uint16 const instanceMapId = fields[0].GetUInt16();
+ auto& vector = _instanceSpawnGroupStore[instanceMapId];
+ vector.emplace_back();
+ InstanceSpawnGroupInfo& info = vector.back();
+ info.SpawnGroupId = spawnGroupId;
+ info.BossStateId = fields[1].GetUInt8();
+
+ uint8 const ALL_STATES = (1 << TO_BE_DECIDED) - 1;
+ uint8 const states = fields[2].GetUInt8();
+ if (states & ~ALL_STATES)
+ {
+ info.BossStates = states & ALL_STATES;
+ TC_LOG_ERROR("sql.sql", "Instance spawn group (%u,%u) had invalid boss state mask %u - truncated to %u.", instanceMapId, spawnGroupId, states, info.BossStates);
+ }
+ else
+ info.BossStates = states;
+
+ uint8 const flags = fields[4].GetUInt8();
+ if (flags & ~InstanceSpawnGroupInfo::FLAG_ALL)
+ {
+ info.Flags = flags & InstanceSpawnGroupInfo::FLAG_ALL;
+ TC_LOG_ERROR("sql.sql", "Instance spawn group (%u,%u) had invalid flags %u - truncated to %u.", instanceMapId, spawnGroupId, flags, info.Flags);
+ }
+ else
+ info.Flags = flags;
+
+ ++n;
+ } while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u instance spawn groups in %u ms", n, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void ObjectMgr::OnDeleteSpawnData(SpawnData const* data)
+{
+ auto templateIt = _spawnGroupDataStore.find(data->spawnGroupData->groupId);
+ ASSERT(templateIt != _spawnGroupDataStore.end(), "Creature data for (%u,%u) is being deleted and has invalid spawn group index %u!", uint32(data->type), data->spawnId, data->spawnGroupData->groupId);
+ if (templateIt->second.flags & SPAWNGROUP_FLAG_SYSTEM) // system groups don't store their members in the map
+ return;
+
+ auto pair = _spawnGroupMapStore.equal_range(data->spawnGroupData->groupId);
+ for (auto it = pair.first; it != pair.second; ++it)
+ {
+ if (it->second != data)
+ continue;
+ _spawnGroupMapStore.erase(it);
+ return;
+ }
+ ASSERT(false, "Spawn data (%u,%u) being removed is member of spawn group %u, but not actually listed in the lookup table for that group!", uint32(data->type), data->spawnId, data->spawnGroupData->groupId);
+}
+
void ObjectMgr::AddGameobjectToGrid(ObjectGuid::LowType guid, GameObjectData const* data)
{
uint8 mask = data->spawnMask;
@@ -2218,8 +2402,8 @@ void ObjectMgr::AddGameobjectToGrid(ObjectGuid::LowType guid, GameObjectData con
{
if (mask & 1)
{
- CellCoord cellCoord = Trinity::ComputeCellCoord(data->posX, data->posY);
- CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()];
+ CellCoord cellCoord = Trinity::ComputeCellCoord(data->spawnPoint.GetPositionX(), data->spawnPoint.GetPositionY());
+ CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->spawnPoint.GetMapId(), i)][cellCoord.GetId()];
cell_guids.gameobjects.insert(guid);
}
}
@@ -2232,8 +2416,8 @@ void ObjectMgr::RemoveGameobjectFromGrid(ObjectGuid::LowType guid, GameObjectDat
{
if (mask & 1)
{
- CellCoord cellCoord = Trinity::ComputeCellCoord(data->posX, data->posY);
- CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()];
+ CellCoord cellCoord = Trinity::ComputeCellCoord(data->spawnPoint.GetPositionX(), data->spawnPoint.GetPositionY());
+ CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->spawnPoint.GetMapId(), i)][cellCoord.GetId()];
cell_guids.gameobjects.erase(guid);
}
}
@@ -3011,7 +3195,7 @@ void ObjectMgr::LoadVehicleTemplateAccessories()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 vehicle template accessories. DB table `vehicle_template_accessory` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 vehicle template accessories. DB table `vehicle_template_accessory` is empty.");
return;
}
@@ -3105,7 +3289,7 @@ void ObjectMgr::LoadPetLevelInfo()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 level pet stats definitions. DB table `pet_levelstats` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 level pet stats definitions. DB table `pet_levelstats` is empty.");
return;
}
@@ -3399,7 +3583,7 @@ void ObjectMgr::LoadPlayerInfo()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 player create skills. DB table `playercreateinfo_skills` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 player create skills. DB table `playercreateinfo_skills` is empty.");
}
else
{
@@ -3473,7 +3657,7 @@ void ObjectMgr::LoadPlayerInfo()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 player create spells. DB table `playercreateinfo_spell_custom` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 player create spells. DB table `playercreateinfo_spell_custom` is empty.");
}
else
{
@@ -3534,7 +3718,7 @@ void ObjectMgr::LoadPlayerInfo()
QueryResult result = WorldDatabase.PQuery("SELECT raceMask, classMask, spell FROM playercreateinfo_cast_spell");
if (!result)
- TC_LOG_ERROR("server.loading", ">> Loaded 0 player create cast spells. DB table `playercreateinfo_cast_spell` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 player create cast spells. DB table `playercreateinfo_cast_spell` is empty.");
else
{
uint32 count = 0;
@@ -3591,7 +3775,7 @@ void ObjectMgr::LoadPlayerInfo()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 player create actions. DB table `playercreateinfo_action` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 player create actions. DB table `playercreateinfo_action` is empty.");
}
else
{
@@ -4019,7 +4203,7 @@ void ObjectMgr::LoadQuests()
" FROM quest_template");
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 quests definitions. DB table `quest_template` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 quests definitions. DB table `quest_template` is empty.");
return;
}
@@ -4070,7 +4254,7 @@ void ObjectMgr::LoadQuests()
{
QueryResult result = WorldDatabase.PQuery("SELECT %s FROM %s", loader.QueryFields, loader.TableName);
if (!result)
- TC_LOG_ERROR("server.loading", ">> Loaded 0 quest %s. DB table `%s` is empty.", loader.TableDesc, loader.TableName);
+ TC_LOG_INFO("server.loading", ">> Loaded 0 quest %s. DB table `%s` is empty.", loader.TableDesc, loader.TableName);
else
{
do
@@ -4881,7 +5065,7 @@ void ObjectMgr::LoadScripts(ScriptsType type)
case SCRIPT_COMMAND_RESPAWN_GAMEOBJECT:
{
- GameObjectData const* data = GetGOData(tmp.RespawnGameobject.GOGuid);
+ GameObjectData const* data = GetGameObjectData(tmp.RespawnGameobject.GOGuid);
if (!data)
{
TC_LOG_ERROR("sql.sql", "Table `%s` has invalid gameobject (GUID: %u) in SCRIPT_COMMAND_RESPAWN_GAMEOBJECT for script id %u",
@@ -4931,7 +5115,7 @@ void ObjectMgr::LoadScripts(ScriptsType type)
case SCRIPT_COMMAND_OPEN_DOOR:
case SCRIPT_COMMAND_CLOSE_DOOR:
{
- GameObjectData const* data = GetGOData(tmp.ToggleDoor.GOGuid);
+ GameObjectData const* data = GetGameObjectData(tmp.ToggleDoor.GOGuid);
if (!data)
{
TC_LOG_ERROR("sql.sql", "Table `%s` has invalid gameobject (GUID: %u) in %s for script id %u",
@@ -5409,7 +5593,7 @@ void ObjectMgr::LoadInstanceEncounters()
QueryResult result = WorldDatabase.Query("SELECT entry, creditType, creditEntry, lastEncounterDungeon FROM instance_encounters");
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 instance encounters, table is empty!");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 instance encounters, table is empty!");
return;
}
@@ -5695,6 +5879,10 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp)
stmt->setUInt32(0, itr2->item_guid);
CharacterDatabase.Execute(stmt);
}
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_MAIL_ITEM_BY_ID);
+ stmt->setUInt32(0, m->messageID);
+ CharacterDatabase.Execute(stmt);
}
else
{
@@ -5794,6 +5982,134 @@ void ObjectMgr::LoadQuestAreaTriggers()
TC_LOG_INFO("server.loading", ">> Loaded %u quest trigger points in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
+QuestGreeting const* ObjectMgr::GetQuestGreeting(ObjectGuid guid) const
+{
+ auto itr = _questGreetingStore.find(guid.GetTypeId());
+ if (itr == _questGreetingStore.end())
+ return nullptr;
+
+ auto questItr = itr->second.find(guid.GetEntry());
+ if (questItr == itr->second.end())
+ return nullptr;
+
+ return questItr->second;
+}
+
+void ObjectMgr::LoadQuestGreetings()
+{
+ uint32 oldMSTime = getMSTime();
+
+ _questGreetingStore.clear(); // need for reload case
+
+ // 0 1 2 3 4
+ QueryResult result = WorldDatabase.Query("SELECT ID, Type, GreetEmoteType, GreetEmoteDelay, Greeting FROM quest_greeting");
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 quest greetings. DB table `quest_greeting` is empty.");
+ return;
+ }
+
+ _questGreetingStore.rehash(result->GetRowCount());
+
+ uint32 count = 0;
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 id = fields[0].GetUInt32();
+ uint8 type = fields[1].GetUInt8();
+ // overwrite
+ switch (type)
+ {
+ case 0: // Creature
+ type = TYPEID_UNIT;
+ if (!sObjectMgr->GetCreatureTemplate(id))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `quest_greeting`: creature template (entry: %u) does not exist.", id);
+ continue;
+ }
+ break;
+ case 1: // GameObject
+ type = TYPEID_GAMEOBJECT;
+ if (!sObjectMgr->GetGameObjectTemplate(id))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `quest_greeting`: gameobject template (entry: %u) does not exist.", id);
+ continue;
+ }
+ break;
+ default:
+ TC_LOG_ERROR("sql.sql", "Table `quest_greeting`: unknown type = %u for entry = %u. Skipped.", type, id);
+ continue;
+ }
+
+ uint16 greetEmoteType = fields[2].GetUInt16();
+
+ if (greetEmoteType > 0 && !sEmotesStore.LookupEntry(greetEmoteType))
+ {
+ TC_LOG_DEBUG("sql.sql", "Table `quest_greeting`: entry %u has greetEmoteType = %u but emote does not exist. Set to 0.", id, greetEmoteType);
+ greetEmoteType = 0;
+ }
+
+ uint32 greetEmoteDelay = fields[3].GetUInt32();
+ std::string greeting = fields[4].GetString();
+
+ _questGreetingStore[type][id] = new QuestGreeting(greetEmoteType, greetEmoteDelay, greeting);
+
+ ++count;
+ }
+ while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u quest_greeting in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void ObjectMgr::LoadQuestGreetingsLocales()
+{
+ uint32 oldMSTime = getMSTime();
+
+ _questGreetingLocaleStore.clear(); // need for reload case
+
+ // 0 1 2 3
+ QueryResult result = WorldDatabase.Query("SELECT ID, Type, Locale, Greeting FROM quest_greeting_locale");
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 quest_greeting locales. DB table `quest_greeting_locale` is empty.");
+ return;
+ }
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 id = fields[0].GetUInt32();
+ uint8 type = fields[1].GetUInt8();
+ // overwrite
+ switch (type)
+ {
+ case 0: // Creature
+ type = TYPEID_UNIT;
+ break;
+ case 1: // GameObject
+ type = TYPEID_GAMEOBJECT;
+ break;
+ default:
+ break;
+ }
+
+ std::string localeName = fields[2].GetString();
+ std::string greeting = fields[3].GetString();
+
+ QuestGreetingLocale& data = _questGreetingLocaleStore[MAKE_PAIR32(id, type)];
+ LocaleConstant locale = GetLocaleByName(localeName);
+ if (locale == LOCALE_enUS)
+ continue;
+
+ AddLocaleString(greeting, locale, data.greeting);
+ } while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u quest greeting locale strings in %u ms", uint32(_questGreetingLocaleStore.size()), GetMSTimeDiffToNow(oldMSTime));
+}
+
void ObjectMgr::LoadTavernAreaTriggers()
{
uint32 oldMSTime = getMSTime();
@@ -6586,7 +6902,7 @@ uint32 ObjectMgr::GenerateGameObjectSpawnId()
{
if (_gameObjectSpawnId >= uint32(0xFFFFFF))
{
- TC_LOG_ERROR("misc", "Creature spawn id overflow!! Can't continue, shutting down server. Search on forum for TCE00007 for more info. ");
+ TC_LOG_ERROR("misc", "GameObject spawn id overflow!! Can't continue, shutting down server. Search on forum for TCE00007 for more info. ");
World::StopNow(ERROR_EXIT_CODE);
}
return _gameObjectSpawnId++;
@@ -6937,7 +7253,7 @@ void ObjectMgr::LoadExplorationBaseXP()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 BaseXP definitions. DB table `exploration_basexp` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 BaseXP definitions. DB table `exploration_basexp` is empty.");
return;
}
@@ -7044,7 +7360,7 @@ void ObjectMgr::LoadReputationRewardRate()
QueryResult result = WorldDatabase.Query("SELECT faction, quest_rate, quest_daily_rate, quest_weekly_rate, quest_monthly_rate, quest_repeatable_rate, creature_rate, spell_rate FROM reputation_reward_rate");
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded `reputation_reward_rate`, table is empty!");
+ TC_LOG_INFO("server.loading", ">> Loaded `reputation_reward_rate`, table is empty!");
return;
}
@@ -7139,7 +7455,7 @@ void ObjectMgr::LoadReputationOnKill()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 creature award reputation definitions. DB table `creature_onkill_reputation` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 creature award reputation definitions. DB table `creature_onkill_reputation` is empty.");
return;
}
@@ -7299,7 +7615,7 @@ void ObjectMgr::LoadPointsOfInterest()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 Points of Interest definitions. DB table `points_of_interest` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 Points of Interest definitions. DB table `points_of_interest` is empty.");
return;
}
@@ -7344,7 +7660,7 @@ void ObjectMgr::LoadQuestPOI()
QueryResult result = WorldDatabase.Query("SELECT QuestID, id, ObjectiveIndex, MapID, WorldMapAreaId, Floor, Priority, Flags FROM quest_poi order by QuestID");
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 quest POI definitions. DB table `quest_poi` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 quest POI definitions. DB table `quest_poi` is empty.");
return;
}
@@ -7436,7 +7752,7 @@ void ObjectMgr::LoadNPCSpellClickSpells()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 spellclick spells. DB table `npc_spellclick_spells` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 spellclick spells. DB table `npc_spellclick_spells` is empty.");
return;
}
@@ -7497,17 +7813,23 @@ void ObjectMgr::DeleteCreatureData(ObjectGuid::LowType guid)
// remove mapid*cellid -> guid_set map
CreatureData const* data = GetCreatureData(guid);
if (data)
+ {
RemoveCreatureFromGrid(guid, data);
+ OnDeleteSpawnData(data);
+ }
_creatureDataStore.erase(guid);
}
-void ObjectMgr::DeleteGOData(ObjectGuid::LowType guid)
+void ObjectMgr::DeleteGameObjectData(ObjectGuid::LowType guid)
{
// remove mapid*cellid -> guid_set map
- GameObjectData const* data = GetGOData(guid);
+ GameObjectData const* data = GetGameObjectData(guid);
if (data)
+ {
RemoveGameobjectFromGrid(guid, data);
+ OnDeleteSpawnData(data);
+ }
_gameObjectDataStore.erase(guid);
}
@@ -7524,7 +7846,7 @@ void ObjectMgr::LoadQuestRelationsHelper(QuestRelations& map, QuestRelationsReve
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 quest relations from `%s`, table is empty.", table.c_str());
+ TC_LOG_INFO("server.loading", ">> Loaded 0 quest relations from `%s`, table is empty.", table.c_str());
return;
}
@@ -7550,7 +7872,7 @@ void ObjectMgr::LoadQuestRelationsHelper(QuestRelations& map, QuestRelationsReve
if (reverseMap)
reverseMap->insert(QuestRelationsReverse::value_type(quest, id));
}
- else if (starter)
+ else
poolRelationMap->insert(PooledQuestRelation::value_type(quest, id));
++count;
@@ -7884,7 +8206,7 @@ bool ObjectMgr::LoadTrinityStrings()
QueryResult result = WorldDatabase.Query("SELECT entry, content_default, content_loc1, content_loc2, content_loc3, content_loc4, content_loc5, content_loc6, content_loc7, content_loc8 FROM trinity_string");
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 trinity strings. DB table `trinity_string` is empty. You have imported an incorrect database for more info search for TCE00003 on forum.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 trinity strings. DB table `trinity_string` is empty. You have imported an incorrect database for more info search for TCE00003 on forum.");
return false;
}
@@ -7930,7 +8252,7 @@ void ObjectMgr::LoadFishingBaseSkillLevel()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 areas for fishing base skill level. DB table `skill_fishing_base_level` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 areas for fishing base skill level. DB table `skill_fishing_base_level` is empty.");
return;
}
@@ -8049,7 +8371,7 @@ void ObjectMgr::LoadGameTele()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 GameTeleports. DB table `game_tele` is empty!");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 GameTeleports. DB table `game_tele` is empty!");
return;
}
@@ -8207,7 +8529,7 @@ void ObjectMgr::LoadMailLevelRewards()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 level dependent mail rewards. DB table `mail_level_reward` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 level dependent mail rewards. DB table `mail_level_reward` is empty.");
return;
}
@@ -8474,7 +8796,7 @@ void ObjectMgr::LoadGossipMenu()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 gossip_menu IDs. DB table `gossip_menu` is empty!");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 gossip_menu IDs. DB table `gossip_menu` is empty!");
return;
}
@@ -8512,7 +8834,7 @@ void ObjectMgr::LoadGossipMenuItems()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 gossip_menu_option IDs. DB table `gossip_menu_option` is empty!");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 gossip_menu_option IDs. DB table `gossip_menu_option` is empty!");
return;
}
@@ -8733,7 +9055,7 @@ void ObjectMgr::LoadScriptNames()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded empty set of Script Names!");
+ TC_LOG_INFO("server.loading", ">> Loaded empty set of Script Names!");
return;
}
@@ -9002,7 +9324,7 @@ void ObjectMgr::LoadFactionChangeAchievements()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 faction change achievement pairs. DB table `player_factionchange_achievement` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 faction change achievement pairs. DB table `player_factionchange_achievement` is empty.");
return;
}
@@ -9072,7 +9394,7 @@ void ObjectMgr::LoadFactionChangeQuests()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 faction change quest pairs. DB table `player_factionchange_quests` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 faction change quest pairs. DB table `player_factionchange_quests` is empty.");
return;
}
@@ -9142,7 +9464,7 @@ void ObjectMgr::LoadFactionChangeSpells()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 faction change spell pairs. DB table `player_factionchange_spells` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 faction change spell pairs. DB table `player_factionchange_spells` is empty.");
return;
}
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 95e7019dacf..8a07723a34e 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -23,8 +23,10 @@
#include "ConditionMgr.h"
#include "CreatureData.h"
#include "DatabaseEnvFwd.h"
+#include "Errors.h"
#include "GameObjectData.h"
#include "ItemTemplate.h"
+#include "IteratorPair.h"
#include "NPCHandler.h"
#include "ObjectDefines.h"
#include "ObjectGuid.h"
@@ -38,6 +40,7 @@
class Item;
class Unit;
class Vehicle;
+class Map;
struct AccessRequirement;
struct DeclinedName;
struct DungeonEncounterEntry;
@@ -98,7 +101,7 @@ struct TempSummonData
// DB scripting commands
enum ScriptCommands
{
- SCRIPT_COMMAND_TALK = 0, // source/target = Creature, target = any, datalong = talk type (0=say, 1=whisper, 2=yell, 3=emote text, 4=boss emote text), datalong2 & 1 = player talk (instead of creature), dataint = string_id
+ SCRIPT_COMMAND_TALK = 0, // source/target = Creature, target = any, datalong = talk type (see ChatType enum), datalong2 & 1 = player talk (instead of creature), dataint = string_id
SCRIPT_COMMAND_EMOTE = 1, // source/target = Creature, datalong = emote id, datalong2 = 0: set emote state; > 0: play emote state
SCRIPT_COMMAND_FIELD_SET = 2, // source/target = Creature, datalong = field id, datalog2 = value
SCRIPT_COMMAND_MOVE_TO = 3, // source/target = Creature, datalong2 = time to reach, x/y/z = destination
@@ -419,6 +422,21 @@ std::string GetScriptsTableNameByType(ScriptsType type);
ScriptMapMap* GetScriptsMapByType(ScriptsType type);
std::string GetScriptCommandName(ScriptCommands command);
+struct TC_GAME_API InstanceSpawnGroupInfo
+{
+ enum
+ {
+ FLAG_ACTIVATE_SPAWN = 0x01,
+ FLAG_BLOCK_SPAWN = 0x02,
+
+ FLAG_ALL = (FLAG_ACTIVATE_SPAWN | FLAG_BLOCK_SPAWN)
+ };
+ uint8 BossStateId;
+ uint8 BossStates;
+ uint32 SpawnGroupId;
+ uint8 Flags;
+};
+
struct TC_GAME_API SpellClickInfo
{
uint32 spellId;
@@ -514,6 +532,11 @@ struct TrinityString
std::vector<std::string> Content;
};
+struct QuestGreetingLocale
+{
+ std::vector<std::string> greeting;
+};
+
typedef std::map<ObjectGuid, ObjectGuid> LinkedRespawnContainer;
typedef std::unordered_map<uint32, CreatureTemplate> CreatureTemplateContainer;
typedef std::unordered_map<uint32, CreatureAddon> CreatureTemplateAddonContainer;
@@ -529,6 +552,9 @@ typedef std::unordered_map<uint32, GameObjectTemplateAddon> GameObjectTemplateAd
typedef std::unordered_map<ObjectGuid::LowType, GameObjectData> GameObjectDataContainer;
typedef std::unordered_map<ObjectGuid::LowType, GameObjectAddon> GameObjectAddonContainer;
typedef std::unordered_map<uint32, std::vector<uint32>> GameObjectQuestItemMap;
+typedef std::unordered_map<uint32, SpawnGroupTemplateData> SpawnGroupDataContainer;
+typedef std::multimap<uint32, SpawnData const*> SpawnGroupLinkContainer;
+typedef std::unordered_map<uint16, std::vector<InstanceSpawnGroupInfo>> InstanceSpawnGroupContainer;
typedef std::map<TempSummonGroupKey, std::vector<TempSummonData>> TempSummonDataContainer;
typedef std::unordered_map<uint32, CreatureLocale> CreatureLocaleContainer;
typedef std::unordered_map<uint32, GameObjectLocale> GameObjectLocaleContainer;
@@ -553,6 +579,7 @@ struct PointOfInterestLocale
};
typedef std::unordered_map<uint32, PointOfInterestLocale> PointOfInterestLocaleContainer;
+typedef std::unordered_map<uint32, QuestGreetingLocale> QuestGreetingLocaleContainer;
typedef std::unordered_map<uint32, TrinityString> TrinityStringContainer;
@@ -773,6 +800,19 @@ struct QuestPOIWrapper
typedef std::unordered_map<uint32, QuestPOIWrapper> QuestPOIContainer;
+struct QuestGreeting
+{
+ uint16 greetEmoteType;
+ uint32 greetEmoteDelay;
+ std::string greeting;
+
+ QuestGreeting() : greetEmoteType(0), greetEmoteDelay(0) { }
+ QuestGreeting(uint16 _greetEmoteType, uint32 _greetEmoteDelay, std::string _greeting)
+ : greetEmoteType(_greetEmoteType), greetEmoteDelay(_greetEmoteDelay), greeting(_greeting) { }
+};
+
+typedef std::unordered_map<uint8, std::unordered_map<uint32, QuestGreeting const*>> QuestGreetingContainer;
+
struct GraveyardData
{
uint32 safeLocId;
@@ -803,6 +843,7 @@ SkillRangeType GetSkillRangeType(SkillRaceClassInfoEntry const* rcEntry);
#define MAX_CHARTER_NAME 24 // max allowed by client name length
TC_GAME_API bool normalizePlayerName(std::string& name);
+#define SPAWNGROUP_MAP_UNSET 0xFFFFFFFF
struct LanguageDesc
{
@@ -976,6 +1017,7 @@ class TC_GAME_API ObjectMgr
}
GossipText const* GetGossipText(uint32 Text_ID) const;
+ QuestGreeting const* GetQuestGreeting(ObjectGuid guid) const;
WorldSafeLocsEntry const* GetDefaultGraveyard(uint32 team) const;
WorldSafeLocsEntry const* GetClosestGraveyard(float x, float y, float z, uint32 MapId, uint32 team) const;
@@ -1120,7 +1162,10 @@ class TC_GAME_API ObjectMgr
void LoadCreatureModelInfo();
void LoadEquipmentTemplates();
void LoadGameObjectLocales();
- void LoadGameobjects();
+ void LoadGameObjects();
+ void LoadSpawnGroupTemplates();
+ void LoadSpawnGroups();
+ void LoadInstanceSpawnGroups();
void LoadItemTemplates();
void LoadItemLocales();
void LoadItemSetNames();
@@ -1130,6 +1175,7 @@ class TC_GAME_API ObjectMgr
void LoadPageTextLocales();
void LoadGossipMenuItemsLocales();
void LoadPointOfInterestLocales();
+ void LoadQuestGreetingsLocales();
void LoadInstanceTemplate();
void LoadInstanceEncounters();
void LoadMailLevelRewards();
@@ -1141,6 +1187,7 @@ class TC_GAME_API ObjectMgr
void LoadAreaTriggerTeleports();
void LoadAccessRequirements();
void LoadQuestAreaTriggers();
+ void LoadQuestGreetings();
void LoadAreaTriggerScripts();
void LoadTavernAreaTriggers();
void LoadGameObjectForQuests();
@@ -1202,8 +1249,14 @@ class TC_GAME_API ObjectMgr
uint64 GenerateEquipmentSetGuid();
uint32 GenerateMailID();
uint32 GeneratePetNumber();
- uint32 GenerateCreatureSpawnId();
- uint32 GenerateGameObjectSpawnId();
+ ObjectGuid::LowType GenerateCreatureSpawnId();
+ ObjectGuid::LowType GenerateGameObjectSpawnId();
+
+ SpawnGroupTemplateData const* GetSpawnGroupData(uint32 groupId) const { auto it = _spawnGroupDataStore.find(groupId); return it != _spawnGroupDataStore.end() ? &it->second : nullptr; }
+ SpawnGroupTemplateData const* GetDefaultSpawnGroup() const { return &_spawnGroupDataStore.at(0); }
+ SpawnGroupTemplateData const* GetLegacySpawnGroup() const { return &_spawnGroupDataStore.at(1); }
+ Trinity::IteratorPair<SpawnGroupLinkContainer::const_iterator> GetSpawnDataForGroup(uint32 groupId) const { return Trinity::Containers::MapEqualRange(_spawnGroupMapStore, groupId); }
+ std::vector<InstanceSpawnGroupInfo> const* GetSpawnGroupsForInstance(uint32 instanceId) const { auto it = _instanceSpawnGroupStore.find(instanceId); return it != _instanceSpawnGroupStore.end() ? &it->second : nullptr; }
MailLevelReward const* GetMailLevelReward(uint32 level, uint32 raceMask) const
{
@@ -1254,6 +1307,18 @@ class TC_GAME_API ObjectMgr
return nullptr;
}
+ SpawnData const* GetSpawnData(SpawnObjectType type, ObjectGuid::LowType guid)
+ {
+ if (type == SPAWN_TYPE_CREATURE)
+ return GetCreatureData(guid);
+ else if (type == SPAWN_TYPE_GAMEOBJECT)
+ return GetGameObjectData(guid);
+ else
+ ASSERT(false, "Invalid spawn object type %u", uint32(type));
+ return nullptr;
+ }
+ void OnDeleteSpawnData(SpawnData const* data);
+ CreatureDataContainer const& GetAllCreatureData() const { return _creatureDataStore; }
CreatureData const* GetCreatureData(ObjectGuid::LowType guid) const
{
CreatureDataContainer::const_iterator itr = _creatureDataStore.find(guid);
@@ -1274,6 +1339,15 @@ class TC_GAME_API ObjectMgr
if (itr == _creatureLocaleStore.end()) return nullptr;
return &itr->second;
}
+ GameObjectDataContainer const& GetAllGameObjectData() const { return _gameObjectDataStore; }
+ GameObjectData const* GetGameObjectData(ObjectGuid::LowType guid) const
+ {
+ GameObjectDataContainer::const_iterator itr = _gameObjectDataStore.find(guid);
+ if (itr == _gameObjectDataStore.end()) return nullptr;
+ return &itr->second;
+ }
+ GameObjectData& NewOrExistGameObjectData(ObjectGuid::LowType guid) { return _gameObjectDataStore[guid]; }
+ void DeleteGameObjectData(ObjectGuid::LowType guid);
GameObjectLocale const* GetGameObjectLocale(uint32 entry) const
{
GameObjectLocaleContainer::const_iterator itr = _gameObjectLocaleStore.find(entry);
@@ -1322,15 +1396,12 @@ class TC_GAME_API ObjectMgr
if (itr == _pointOfInterestLocaleStore.end()) return nullptr;
return &itr->second;
}
-
- GameObjectData const* GetGOData(ObjectGuid::LowType guid) const
+ QuestGreetingLocale const* GetQuestGreetingLocale(uint32 id) const
{
- GameObjectDataContainer::const_iterator itr = _gameObjectDataStore.find(guid);
- if (itr == _gameObjectDataStore.end()) return nullptr;
+ QuestGreetingLocaleContainer::const_iterator itr = _questGreetingLocaleStore.find(id);
+ if (itr == _questGreetingLocaleStore.end()) return nullptr;
return &itr->second;
}
- GameObjectData& NewGOData(ObjectGuid::LowType guid) { return _gameObjectDataStore[guid]; }
- void DeleteGOData(ObjectGuid::LowType guid);
TrinityString const* GetTrinityString(uint32 entry) const
{
@@ -1349,7 +1420,7 @@ class TC_GAME_API ObjectMgr
void RemoveCreatureFromGrid(ObjectGuid::LowType guid, CreatureData const* data);
void AddGameobjectToGrid(ObjectGuid::LowType guid, GameObjectData const* data);
void RemoveGameobjectFromGrid(ObjectGuid::LowType guid, GameObjectData const* data);
- ObjectGuid::LowType AddGOData(uint32 entry, uint32 map, Position const& pos, QuaternionData const& rot, uint32 spawntimedelay = 0);
+ ObjectGuid::LowType AddGameObjectData(uint32 entry, uint32 map, Position const& pos, QuaternionData const& rot, uint32 spawntimedelay = 0);
ObjectGuid::LowType AddCreatureData(uint32 entry, uint32 map, Position const& pos, uint32 spawntimedelay = 0);
// reserved names
@@ -1458,8 +1529,8 @@ class TC_GAME_API ObjectMgr
std::atomic<uint32> _mailId;
std::atomic<uint32> _hiPetNumber;
- uint32 _creatureSpawnId;
- uint32 _gameObjectSpawnId;
+ ObjectGuid::LowType _creatureSpawnId;
+ ObjectGuid::LowType _gameObjectSpawnId;
// first free low guid for selected guid type
template<HighGuid high>
@@ -1484,6 +1555,7 @@ class TC_GAME_API ObjectMgr
TavernAreaTriggerContainer _tavernAreaTriggerStore;
GameObjectForQuestContainer _gameObjectForQuestStore;
GossipTextContainer _gossipTextStore;
+ QuestGreetingContainer _questGreetingStore;
AreaTriggerContainer _areaTriggerStore;
AreaTriggerScriptContainer _areaTriggerScriptStore;
AccessRequirementContainer _accessRequirementStore;
@@ -1579,6 +1651,9 @@ class TC_GAME_API ObjectMgr
GameObjectLocaleContainer _gameObjectLocaleStore;
GameObjectTemplateContainer _gameObjectTemplateStore;
GameObjectTemplateAddonContainer _gameObjectTemplateAddonStore;
+ SpawnGroupDataContainer _spawnGroupDataStore;
+ SpawnGroupLinkContainer _spawnGroupMapStore;
+ InstanceSpawnGroupContainer _instanceSpawnGroupStore;
/// Stores temp summon data grouped by summoner's entry, summoner's type and group id
TempSummonDataContainer _tempSummonDataStore;
@@ -1591,6 +1666,7 @@ class TC_GAME_API ObjectMgr
PageTextLocaleContainer _pageTextLocaleStore;
GossipMenuItemsLocaleContainer _gossipMenuItemsLocaleStore;
PointOfInterestLocaleContainer _pointOfInterestLocaleStore;
+ QuestGreetingLocaleContainer _questGreetingLocaleStore;
TrinityStringContainer _trinityStringStore;
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h
index 897e43d5e03..16583516243 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.h
@@ -552,6 +552,11 @@ namespace Trinity
: ContainerInserter<Player*>(container),
i_phaseMask(searcher->GetPhaseMask()), i_check(check) { }
+ template<typename Container>
+ PlayerListSearcher(uint32 phaseMask, Container& container, Check & check)
+ : ContainerInserter<Player*>(container),
+ i_phaseMask(phaseMask), i_check(check) { }
+
void Visit(PlayerMapType &m);
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) { }
@@ -928,9 +933,9 @@ namespace Trinity
return false;
float searchRadius = i_range;
- if (i_incOwnRadius)
+ if (i_incOwnRadius)
searchRadius += i_obj->GetCombatReach();
- if (i_incTargetRadius)
+ if (i_incTargetRadius)
searchRadius += u->GetCombatReach();
if (!u->IsInMap(i_obj) || !u->InSamePhase(i_obj) || !u->IsWithinDoubleVerticalCylinder(i_obj, searchRadius, searchRadius))
@@ -954,7 +959,7 @@ namespace Trinity
class AnyGroupedUnitInObjectRangeCheck
{
public:
- AnyGroupedUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool raid, bool playerOnly = false, bool incOwnRadius = true, bool incTargetRadius = true)
+ AnyGroupedUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool raid, bool playerOnly = false, bool incOwnRadius = true, bool incTargetRadius = true)
: _source(obj), _refUnit(funit), _range(range), _raid(raid), _playerOnly(playerOnly), i_incOwnRadius(incOwnRadius), i_incTargetRadius(incTargetRadius) { }
bool operator()(Unit* u) const
@@ -977,9 +982,9 @@ namespace Trinity
return false;
float searchRadius = _range;
- if (i_incOwnRadius)
+ if (i_incOwnRadius)
searchRadius += _source->GetCombatReach();
- if (i_incTargetRadius)
+ if (i_incTargetRadius)
searchRadius += u->GetCombatReach();
return u->IsInMap(_source) && u->InSamePhase(_source) && u->IsWithinDoubleVerticalCylinder(_source, searchRadius, searchRadius);
@@ -1022,7 +1027,7 @@ namespace Trinity
bool operator()(Unit* u)
{
if (u->isTargetableForAttack() && i_obj->IsWithinDistInMap(u, i_range) &&
- !i_funit->IsFriendlyTo(u) && i_funit->CanSeeOrDetect(u))
+ (i_funit->IsInCombatWith(u) || i_funit->IsHostileTo(u)) && i_obj->CanSeeOrDetect(u))
{
i_range = i_obj->GetDistance(u); // use found unit range as new range limit for next check
return true;
@@ -1064,9 +1069,9 @@ namespace Trinity
return false;
float searchRadius = i_range;
- if (i_incOwnRadius)
+ if (i_incOwnRadius)
searchRadius += i_obj->GetCombatReach();
- if (i_incTargetRadius)
+ if (i_incTargetRadius)
searchRadius += u->GetCombatReach();
return u->IsInMap(i_obj) && u->InSamePhase(i_obj) && u->IsWithinDoubleVerticalCylinder(i_obj, searchRadius, searchRadius);
@@ -1321,6 +1326,27 @@ namespace Trinity
bool _reqAlive;
};
+ class AnyPlayerInPositionRangeCheck
+ {
+ public:
+ AnyPlayerInPositionRangeCheck(Position const* pos, float range, bool reqAlive = true) : _pos(pos), _range(range), _reqAlive(reqAlive) { }
+ bool operator()(Player* u)
+ {
+ if (_reqAlive && !u->IsAlive())
+ return false;
+
+ if (!u->IsWithinDist3d(_pos, _range))
+ return false;
+
+ return true;
+ }
+
+ private:
+ Position const* _pos;
+ float _range;
+ bool _reqAlive;
+ };
+
class NearestPlayerInObjectRangeCheck
{
public:
diff --git a/src/server/game/Grids/ObjectGridLoader.cpp b/src/server/game/Grids/ObjectGridLoader.cpp
index 653c9d51d11..4dfca6f98c0 100644
--- a/src/server/game/Grids/ObjectGridLoader.cpp
+++ b/src/server/game/Grids/ObjectGridLoader.cpp
@@ -27,6 +27,7 @@
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "World.h"
+#include "ScriptMgr.h"
void ObjectGridEvacuator::Visit(CreatureMapType &m)
{
@@ -119,15 +120,56 @@ void LoadHelper(CellGuidSet const& guid_set, CellCoord &cell, GridRefManager<T>
for (CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid)
{
T* obj = new T;
- ObjectGuid::LowType guid = *i_guid;
- //TC_LOG_INFO("misc", "DEBUG: LoadHelper from table: %s for (guid: %u) Loading", table, guid);
- if (!obj->LoadFromDB(guid, map))
+
+ // Don't spawn at all if there's a respawn time
+ if ((obj->GetTypeId() == TYPEID_UNIT && !map->GetCreatureRespawnTime(*i_guid)) || (obj->GetTypeId() == TYPEID_GAMEOBJECT && !map->GetGORespawnTime(*i_guid)))
{
- delete obj;
- continue;
- }
+ ObjectGuid::LowType guid = *i_guid;
+ //TC_LOG_INFO("misc", "DEBUG: LoadHelper from table: %s for (guid: %u) Loading", table, guid);
- AddObjectHelper(cell, m, count, map, obj);
+ if (obj->GetTypeId() == TYPEID_UNIT)
+ {
+ CreatureData const* cdata = sObjectMgr->GetCreatureData(guid);
+ ASSERT(cdata, "Tried to load creature with spawnId %u, but no such creature exists.", guid);
+ SpawnGroupTemplateData const* const group = cdata->spawnGroupData;
+ // If creature in manual spawn group, don't spawn here, unless group is already active.
+ if (!(group->flags & SPAWNGROUP_FLAG_SYSTEM))
+ if (!map->IsSpawnGroupActive(group->groupId))
+ {
+ delete obj;
+ continue;
+ }
+
+ // If script is blocking spawn, don't spawn but queue for a re-check in a little bit
+ if (!(group->flags & SPAWNGROUP_FLAG_COMPATIBILITY_MODE) && !sScriptMgr->CanSpawn(guid, cdata->id, cdata, map))
+ {
+ map->SaveRespawnTime(SPAWN_TYPE_CREATURE, guid, cdata->id, time(NULL) + urand(4,7), map->GetZoneId(cdata->spawnPoint), Trinity::ComputeGridCoord(cdata->spawnPoint.GetPositionX(), cdata->spawnPoint.GetPositionY()).GetId(), false);
+ delete obj;
+ continue;
+ }
+ }
+ else if (obj->GetTypeId() == TYPEID_GAMEOBJECT)
+ {
+ // If gameobject in manual spawn group, don't spawn here, unless group is already active.
+ GameObjectData const* godata = sObjectMgr->GetGameObjectData(guid);
+ ASSERT(godata, "Tried to load gameobject with spawnId %u, but no such object exists.", guid);
+ if (!(godata->spawnGroupData->flags & SPAWNGROUP_FLAG_SYSTEM))
+ if (!map->IsSpawnGroupActive(godata->spawnGroupData->groupId))
+ {
+ delete obj;
+ continue;
+ }
+ }
+
+ if (!obj->LoadFromDB(guid, map, false, false))
+ {
+ delete obj;
+ continue;
+ }
+ AddObjectHelper(cell, m, count, map, obj);
+ }
+ else
+ delete obj;
}
}
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index 76b7de68ea9..79df88b61a5 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -1534,8 +1534,7 @@ void Group::CountTheRoll(Rolls::iterator rollI, Map* allowedMap)
// remove is_blocked so that the item is lootable by all players
LootItem* item = &(roll->itemSlot >= roll->getLoot()->items.size() ? roll->getLoot()->quest_items[roll->itemSlot - roll->getLoot()->items.size()] : roll->getLoot()->items[roll->itemSlot]);
- if (item)
- item->is_blocked = false;
+ item->is_blocked = false;
}
RollId.erase(rollI);
diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp
index 8b03ff91240..bb8f52b90fd 100644
--- a/src/server/game/Handlers/BattleGroundHandler.cpp
+++ b/src/server/game/Handlers/BattleGroundHandler.cpp
@@ -51,7 +51,8 @@ void WorldSession::HandleBattlemasterHelloOpcode(WorldPacket& recvData)
return;
// Stop the npc if moving
- unit->StopMoving();
+ unit->PauseMovement(sWorld->getIntConfig(CONFIG_CREATURE_STOP_FOR_PLAYER));
+ unit->SetHomePosition(unit->GetPosition());
BattlegroundTypeId bgTypeId = sBattlegroundMgr->GetBattleMasterBG(unit->GetEntry());
diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp
index 6d884ca2ee9..4384ff82474 100644
--- a/src/server/game/Handlers/CalendarHandler.cpp
+++ b/src/server/game/Handlers/CalendarHandler.cpp
@@ -41,6 +41,7 @@ Copied events should probably have a new owner
#include "CharacterCache.h"
#include "DatabaseEnv.h"
#include "DBCStores.h"
+#include "GameEventMgr.h"
#include "Guild.h"
#include "GuildMgr.h"
#include "InstanceSaveMgr.h"
@@ -151,12 +152,10 @@ void WorldSession::HandleCalendarGetCalendar(WorldPacket& /*recvData*/)
data << uint32(boundCounter);
data.append(dataBuffer);
- /// @todo Fix this, how we do know how many and what holidays to send?
- uint32 holidayCount = 0;
- data << uint32(holidayCount);
- for (uint32 i = 0; i < holidayCount; ++i)
+ data << uint32(sGameEventMgr->modifiedHolidays.size());
+ for (uint32 entry : sGameEventMgr->modifiedHolidays)
{
- HolidaysEntry const* holiday = sHolidaysStore.LookupEntry(666);
+ HolidaysEntry const* holiday = sHolidaysStore.LookupEntry(entry);
data << uint32(holiday->Id); // m_ID
data << uint32(holiday->Region); // m_region, might be looping
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 9bdf294c9b3..df8f418c245 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -1560,6 +1560,9 @@ void WorldSession::HandleEquipmentSetUse(WorldPacket& recvData)
InventoryResult msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, sDest, uItem, false);
if (msg == EQUIP_ERR_OK)
{
+ if (_player->CanEquipItem(NULL_SLOT, dstpos, uItem, false) != EQUIP_ERR_OK)
+ continue;
+
_player->RemoveItem(INVENTORY_SLOT_BAG_0, i, true);
_player->StoreItem(sDest, uItem, true);
}
@@ -1572,6 +1575,9 @@ void WorldSession::HandleEquipmentSetUse(WorldPacket& recvData)
if (item->GetPos() == dstpos)
continue;
+ if (_player->CanUnequipItem(dstpos, true) != EQUIP_ERR_OK)
+ continue;
+
_player->SwapItem(item->GetPos(), dstpos);
}
@@ -2084,7 +2090,7 @@ void WorldSession::HandleCharFactionOrRaceChangeCallback(std::shared_ptr<Charact
ss << knownTitles[index] << ' ';
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_TITLES_FACTION_CHANGE);
- stmt->setString(0, ss.str().c_str());
+ stmt->setString(0, ss.str());
stmt->setUInt32(1, lowGuid);
trans->Append(stmt);
diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp
index eb3200ea87d..259bc08838e 100644
--- a/src/server/game/Handlers/ChatHandler.cpp
+++ b/src/server/game/Handlers/ChatHandler.cpp
@@ -126,7 +126,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
// 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)
+ // send in universal language if player in .gm on mode (ignore spell effects)
if (sender->IsGameMaster())
lang = LANG_UNIVERSAL;
else
@@ -216,11 +216,15 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
if (msg.empty())
return;
- if (ChatHandler(this).ParseCommands(msg.c_str()))
- return;
-
+ if (lang == LANG_ADDON)
+ {
+ if (AddonChannelCommandHandler(this).ParseCommands(msg.c_str()))
+ return;
+ }
if (lang != LANG_ADDON)
{
+ if (ChatHandler(this).ParseCommands(msg.c_str()))
+ return;
// Strip invisible characters for non-addon messages
if (sWorld->getBoolConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING))
stripLineInvisibleChars(msg);
@@ -466,7 +470,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
if (Channel* chn = ChannelMgr::GetChannelForPlayerByNamePart(channel, sender))
{
sScriptMgr->OnPlayerChat(sender, type, lang, msg, chn);
- chn->Say(sender->GetGUID(), msg.c_str(), lang);
+ chn->Say(sender->GetGUID(), msg, lang);
}
break;
}
diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp
index 9f3e2a52efe..ee2666c9f96 100644
--- a/src/server/game/Handlers/ItemHandler.cpp
+++ b/src/server/game/Handlers/ItemHandler.cpp
@@ -615,8 +615,8 @@ void WorldSession::SendListInventory(ObjectGuid vendorGuid)
GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
// Stop the npc if moving
- if (vendor->HasUnitState(UNIT_STATE_MOVING))
- vendor->StopMoving();
+ vendor->PauseMovement(sWorld->getIntConfig(CONFIG_CREATURE_STOP_FOR_PLAYER));
+ vendor->SetHomePosition(vendor->GetPosition());
VendorItemData const* items = vendor->GetVendorItems();
if (!items)
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index a632bf1979c..9a130fab45f 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -51,6 +51,7 @@
#include "WhoListStorage.h"
#include "World.h"
#include "WorldPacket.h"
+#include <cstdarg>
#include <zlib.h>
void WorldSession::HandleRepopRequestOpcode(WorldPacket& recvData)
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index 8b64e0e08bb..a8b365e5db2 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -24,9 +24,10 @@
#include "Corpse.h"
#include "Player.h"
#include "MapManager.h"
+#include "MotionMaster.h"
+#include "MovementGenerator.h"
#include "Transport.h"
#include "Battleground.h"
-#include "WaypointMovementGenerator.h"
#include "InstanceSaveMgr.h"
#include "ObjectMgr.h"
#include "Vehicle.h"
@@ -133,8 +134,8 @@ void WorldSession::HandleMoveWorldportAck()
if (!_player->InBattleground())
{
// short preparations to continue flight
- FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top());
- flight->Initialize(GetPlayer());
+ MovementGenerator* movementGenerator = GetPlayer()->GetMotionMaster()->top();
+ movementGenerator->Initialize(GetPlayer());
return;
}
diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp
index ddde13ae860..59344509283 100644
--- a/src/server/game/Handlers/NPCHandler.cpp
+++ b/src/server/game/Handlers/NPCHandler.cpp
@@ -38,6 +38,7 @@
#include "ScriptMgr.h"
#include "SpellInfo.h"
#include "SpellMgr.h"
+#include "World.h"
#include "WorldPacket.h"
enum StableResultCode
@@ -322,11 +323,9 @@ void WorldSession::HandleGossipHelloOpcode(WorldPacket& recvData)
//if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
// GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
- // and if he has pure gossip or is banker and moves or is tabard designer?
- //if (unit->IsArmorer() || unit->IsCivilian() || unit->IsQuestGiver() || unit->IsServiceProvider() || unit->IsGuard())
- {
- unit->StopMoving();
- }
+ // Stop the npc if moving
+ unit->PauseMovement(sWorld->getIntConfig(CONFIG_CREATURE_STOP_FOR_PLAYER));
+ unit->SetHomePosition(unit->GetPosition());
// If spiritguide, no need for gossip menu, just put player into resurrect queue
if (unit->IsSpiritGuide())
diff --git a/src/server/game/Handlers/PetitionsHandler.cpp b/src/server/game/Handlers/PetitionsHandler.cpp
index 4e47f260fff..03087ce5e7e 100644
--- a/src/server/game/Handlers/PetitionsHandler.cpp
+++ b/src/server/game/Handlers/PetitionsHandler.cpp
@@ -420,7 +420,7 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket& recvData)
{
if (_player->getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
{
- SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", _player->GetName().c_str(), ERR_ARENA_TEAM_TARGET_TOO_LOW_S);
+ SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", _player->GetName(), ERR_ARENA_TEAM_TARGET_TOO_LOW_S);
return;
}
@@ -430,13 +430,13 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket& recvData)
if (_player->GetArenaTeamId(slot))
{
- SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName().c_str(), ERR_ALREADY_IN_ARENA_TEAM_S);
+ 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().c_str(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
+ SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
return;
}
}
@@ -549,7 +549,7 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket& recvData)
if (player->getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
{
// player is too low level to join an arena team
- SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName().c_str(), "", ERR_ARENA_TEAM_TARGET_TOO_LOW_S);
+ SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ARENA_TEAM_TARGET_TOO_LOW_S);
return;
}
@@ -560,13 +560,13 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket& recvData)
if (player->GetArenaTeamId(slot))
{
// player is already in an arena team
- SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName().c_str(), "", ERR_ALREADY_IN_ARENA_TEAM_S);
+ 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().c_str(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
+ SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
return;
}
}
diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp
index f95fb01ed36..23c0ac25524 100644
--- a/src/server/game/Handlers/QuestHandler.cpp
+++ b/src/server/game/Handlers/QuestHandler.cpp
@@ -91,8 +91,10 @@ void WorldSession::HandleQuestgiverHelloOpcode(WorldPacket& recvData)
// remove fake death
if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
+
// Stop the npc if moving
- creature->StopMoving();
+ creature->PauseMovement(sWorld->getIntConfig(CONFIG_CREATURE_STOP_FOR_PLAYER));
+ creature->SetHomePosition(creature->GetPosition());
_player->PlayerTalkClass->ClearMenus();
if (creature->AI()->GossipHello(_player))
diff --git a/src/server/game/Handlers/TaxiHandler.cpp b/src/server/game/Handlers/TaxiHandler.cpp
index 3912707ea25..6adc2d04aed 100644
--- a/src/server/game/Handlers/TaxiHandler.cpp
+++ b/src/server/game/Handlers/TaxiHandler.cpp
@@ -18,9 +18,12 @@
#include "WorldSession.h"
#include "Common.h"
+#include "Creature.h"
#include "DatabaseEnv.h"
#include "DBCStores.h"
#include "Log.h"
+#include "MotionMaster.h"
+#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Opcodes.h"
#include "Player.h"
@@ -39,25 +42,22 @@ void WorldSession::HandleTaxiNodeStatusQueryOpcode(WorldPacket& recvData)
void WorldSession::SendTaxiStatus(ObjectGuid guid)
{
- // cheating checks
- Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER);
- if (!unit)
+ Player* const player = GetPlayer();
+ Creature* unit = ObjectAccessor::GetCreature(*player, guid);
+ if (!unit || unit->IsHostileTo(player) || !unit->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_FLIGHTMASTER))
{
TC_LOG_DEBUG("network", "WorldSession::SendTaxiStatus - %s not found or you can't interact with him.", guid.ToString().c_str());
return;
}
- uint32 curloc = sObjectMgr->GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), GetPlayer()->GetTeam());
-
- // not found nearest
- if (curloc == 0)
+ // find taxi node
+ uint32 nearest = sObjectMgr->GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), player->GetTeam());
+ if (!nearest)
return;
- TC_LOG_DEBUG("network", "WORLD: current location %u ", curloc);
-
WorldPacket data(SMSG_TAXINODE_STATUS, 9);
data << guid;
- data << uint8(GetPlayer()->m_taxi.IsTaximaskNodeKnown(curloc) ? 1 : 0);
+ data << uint8(player->m_taxi.IsTaximaskNodeKnown(nearest) ? 1 : 0);
SendPacket(&data);
}
@@ -119,8 +119,7 @@ void WorldSession::SendDoFlight(uint32 mountDisplayId, uint32 path, uint32 pathN
if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
- while (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE)
- GetPlayer()->GetMotionMaster()->MovementExpired(false);
+ GetPlayer()->GetMotionMaster()->Clear(MOTION_SLOT_CONTROLLED);
if (mountDisplayId)
GetPlayer()->Mount(mountDisplayId);
diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp
index 3fa7eb52d6e..154254e25b2 100644
--- a/src/server/game/Instances/InstanceScript.cpp
+++ b/src/server/game/Instances/InstanceScript.cpp
@@ -46,7 +46,7 @@ BossBoundaryData::~BossBoundaryData()
delete it->Boundary;
}
-InstanceScript::InstanceScript(Map* map) : instance(map), completedEncounters(0)
+InstanceScript::InstanceScript(Map* map) : instance(map), completedEncounters(0), _instanceSpawnGroups(sObjectMgr->GetSpawnGroupsForInstance(map->GetId()))
{
#ifdef TRINITY_API_USE_DYNAMIC_LINKING
uint32 scriptId = sObjectMgr->GetInstanceTemplate(map->GetId())->ScriptId;
@@ -186,27 +186,6 @@ void InstanceScript::LoadObjectData(ObjectData const* data, ObjectInfoMap& objec
}
}
-void InstanceScript::UpdateMinionState(Creature* minion, EncounterState state)
-{
- switch (state)
- {
- case NOT_STARTED:
- if (!minion->IsAlive())
- minion->Respawn();
- else if (minion->IsInCombat())
- minion->AI()->EnterEvadeMode();
- break;
- case IN_PROGRESS:
- if (!minion->IsAlive())
- minion->Respawn();
- else if (!minion->GetVictim())
- minion->AI()->DoZoneInCombat();
- break;
- default:
- break;
- }
-}
-
void InstanceScript::UpdateDoorState(GameObject* door)
{
DoorInfoMapBounds range = doors.equal_range(door->GetEntry());
@@ -236,6 +215,60 @@ void InstanceScript::UpdateDoorState(GameObject* door)
door->SetGoState(open ? GO_STATE_ACTIVE : GO_STATE_READY);
}
+void InstanceScript::UpdateMinionState(Creature* minion, EncounterState state)
+{
+ switch (state)
+ {
+ case NOT_STARTED:
+ if (!minion->IsAlive())
+ minion->Respawn();
+ else if (minion->IsInCombat())
+ minion->AI()->EnterEvadeMode();
+ break;
+ case IN_PROGRESS:
+ if (!minion->IsAlive())
+ minion->Respawn();
+ else if (!minion->GetVictim())
+ minion->AI()->DoZoneInCombat();
+ break;
+ default:
+ break;
+ }
+}
+
+void InstanceScript::UpdateSpawnGroups()
+{
+ if (!_instanceSpawnGroups)
+ return;
+ enum states { BLOCK, SPAWN, FORCEBLOCK };
+ std::unordered_map<uint32, states> newStates;
+ for (auto it = _instanceSpawnGroups->begin(), end = _instanceSpawnGroups->end(); it != end; ++it)
+ {
+ InstanceSpawnGroupInfo const& info = *it;
+ states& curValue = newStates[info.SpawnGroupId]; // makes sure there's a BLOCK value in the map
+ if (curValue == FORCEBLOCK) // nothing will change this
+ continue;
+ if (!((1 << GetBossState(info.BossStateId)) & info.BossStates))
+ continue;
+ if (info.Flags & InstanceSpawnGroupInfo::FLAG_BLOCK_SPAWN)
+ curValue = FORCEBLOCK;
+ else if (info.Flags & InstanceSpawnGroupInfo::FLAG_ACTIVATE_SPAWN)
+ curValue = SPAWN;
+ }
+ for (auto const& pair : newStates)
+ {
+ uint32 const groupId = pair.first;
+ bool const doSpawn = (pair.second == SPAWN);
+ if (instance->IsSpawnGroupActive(groupId) == doSpawn)
+ continue; // nothing to do here
+ // if we should spawn group, then spawn it...
+ if (doSpawn)
+ instance->SpawnGroupSpawn(groupId);
+ else // otherwise, set it as inactive so it no longer respawns (but don't despawn it)
+ instance->SetSpawnGroupActive(groupId, false);
+ }
+}
+
BossInfo* InstanceScript::GetBossInfo(uint32 id)
{
ASSERT(id < bosses.size());
@@ -310,7 +343,7 @@ bool InstanceScript::SetBossState(uint32 id, EncounterState state)
if (bossInfo->state == TO_BE_DECIDED) // loading
{
bossInfo->state = state;
- //TC_LOG_ERROR("misc", "Inialize boss %u state as %u.", id, (uint32)state);
+ TC_LOG_DEBUG("scripts", "InstanceScript: Initialize boss %u state as %s (map %u, %u).", id, GetBossStateName(state), instance->GetId(), instance->GetInstanceId());
return false;
}
else
@@ -318,6 +351,12 @@ bool InstanceScript::SetBossState(uint32 id, EncounterState state)
if (bossInfo->state == state)
return false;
+ if (bossInfo->state == DONE)
+ {
+ TC_LOG_ERROR("map", "InstanceScript: Tried to set instance state from %s back to %s for map %u, instance id %u. Blocked!", GetBossStateName(bossInfo->state), GetBossStateName(state), instance->GetId(), instance->GetInstanceId());
+ return false;
+ }
+
if (state == DONE)
for (GuidSet::iterator i = bossInfo->minion.begin(); i != bossInfo->minion.end(); ++i)
if (Creature* minion = instance->GetCreature(*i))
@@ -337,6 +376,7 @@ bool InstanceScript::SetBossState(uint32 id, EncounterState state)
if (Creature* minion = instance->GetCreature(*i))
UpdateMinionState(minion, state);
+ UpdateSpawnGroups();
return true;
}
return false;
@@ -347,6 +387,13 @@ bool InstanceScript::_SkipCheckRequiredBosses(Player const* player /*= nullptr*/
return player && player->GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES);
}
+void InstanceScript::Create()
+{
+ for (size_t i = 0; i < bosses.size(); ++i)
+ SetBossState(i, NOT_STARTED);
+ UpdateSpawnGroups();
+}
+
void InstanceScript::Load(char const* data)
{
if (!data)
@@ -397,6 +444,7 @@ void InstanceScript::ReadSaveDataBossStates(std::istringstream& data)
if (buff < TO_BE_DECIDED)
SetBossState(bossId, EncounterState(buff));
}
+ UpdateSpawnGroups();
}
std::string InstanceScript::GetSaveData()
@@ -691,7 +739,7 @@ void InstanceScript::UpdateEncounterStateForSpellCast(uint32 spellId, Unit* sour
UpdateEncounterState(ENCOUNTER_CREDIT_CAST_SPELL, spellId, source);
}
-std::string InstanceScript::GetBossStateName(uint8 state)
+/*static*/ char const* InstanceScript::GetBossStateName(uint8 state)
{
// See enum EncounterState in InstanceScript.h
switch (state)
diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h
index 55452ebf3c1..d9802aa548b 100644
--- a/src/server/game/Instances/InstanceScript.h
+++ b/src/server/game/Instances/InstanceScript.h
@@ -34,6 +34,7 @@
class AreaBoundary;
class Creature;
class GameObject;
+struct InstanceSpawnGroupInfo;
class Map;
class ModuleReference;
class Player;
@@ -156,7 +157,10 @@ class TC_GAME_API InstanceScript : public ZoneScript
// KEEPING THIS METHOD ONLY FOR BACKWARD COMPATIBILITY !!!
virtual void Initialize() { }
- // On load
+ // On instance load, exactly ONE of these methods will ALWAYS be called:
+ // if we're starting without any saved instance data
+ virtual void Create();
+ // if we're loading existing instance save data
virtual void Load(char const* data);
// When save is needed, this function generates the data
@@ -223,7 +227,7 @@ class TC_GAME_API InstanceScript : public ZoneScript
virtual bool SetBossState(uint32 id, EncounterState state);
EncounterState GetBossState(uint32 id) const { return id < bosses.size() ? bosses[id].state : TO_BE_DECIDED; }
- static std::string GetBossStateName(uint8 state);
+ static char const* GetBossStateName(uint8 state);
CreatureBoundary const* GetBossBoundary(uint32 id) const { return id < bosses.size() ? &bosses[id].boundary : nullptr; }
// Achievement criteria additional requirements check
@@ -249,6 +253,11 @@ class TC_GAME_API InstanceScript : public ZoneScript
uint32 GetEncounterCount() const { return bosses.size(); }
+ // Only used by areatriggers that inherit from OnlyOnceAreaTriggerScript
+ void MarkAreaTriggerDone(uint32 id) { _activatedAreaTriggers.insert(id); }
+ void ResetAreaTriggerDone(uint32 id) { _activatedAreaTriggers.erase(id); }
+ bool IsAreaTriggerDone(uint32 id) const { return _activatedAreaTriggers.find(id) != _activatedAreaTriggers.end(); }
+
protected:
void SetHeaders(std::string const& dataHeaders);
void SetBossNumber(uint32 number) { bosses.resize(number); }
@@ -267,6 +276,8 @@ class TC_GAME_API InstanceScript : public ZoneScript
virtual void UpdateDoorState(GameObject* door);
void UpdateMinionState(Creature* minion, EncounterState state);
+ void UpdateSpawnGroups();
+
// Exposes private data that should never be modified unless exceptional cases.
// Pay very much attention at how the returned BossInfo data is modified to avoid issues.
BossInfo* GetBossInfo(uint32 id);
@@ -293,6 +304,8 @@ class TC_GAME_API InstanceScript : public ZoneScript
ObjectInfoMap _gameObjectInfo;
ObjectGuidMap _objectGuids;
uint32 completedEncounters; // completed encounter mask, bit indexes are DungeonEncounter.dbc boss numbers, used for packets
+ std::vector<InstanceSpawnGroupInfo> const* const _instanceSpawnGroups;
+ std::unordered_set<uint32> _activatedAreaTriggers;
#ifdef TRINITY_API_USE_DYNAMIC_LINKING
// Strong reference to the associated script module
diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp
index 7c6cc28fb48..f93ee0a91bc 100644
--- a/src/server/game/Loot/LootMgr.cpp
+++ b/src/server/game/Loot/LootMgr.cpp
@@ -812,7 +812,7 @@ void LoadLootTemplates_Creature()
if (count)
TC_LOG_INFO("server.loading", ">> Loaded %u creature loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
else
- TC_LOG_ERROR("server.loading", ">> Loaded 0 creature loot templates. DB table `creature_loot_template` is empty");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 creature loot templates. DB table `creature_loot_template` is empty");
}
void LoadLootTemplates_Disenchant()
@@ -845,7 +845,7 @@ void LoadLootTemplates_Disenchant()
if (count)
TC_LOG_INFO("server.loading", ">> Loaded %u disenchanting loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
else
- TC_LOG_ERROR("server.loading", ">> Loaded 0 disenchanting loot templates. DB table `disenchant_loot_template` is empty");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 disenchanting loot templates. DB table `disenchant_loot_template` is empty");
}
void LoadLootTemplates_Fishing()
@@ -868,7 +868,7 @@ void LoadLootTemplates_Fishing()
if (count)
TC_LOG_INFO("server.loading", ">> Loaded %u fishing loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
else
- TC_LOG_ERROR("server.loading", ">> Loaded 0 fishing loot templates. DB table `fishing_loot_template` is empty");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 fishing loot templates. DB table `fishing_loot_template` is empty");
}
void LoadLootTemplates_Gameobject()
@@ -902,7 +902,7 @@ void LoadLootTemplates_Gameobject()
if (count)
TC_LOG_INFO("server.loading", ">> Loaded %u gameobject loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
else
- TC_LOG_ERROR("server.loading", ">> Loaded 0 gameobject loot templates. DB table `gameobject_loot_template` is empty");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 gameobject loot templates. DB table `gameobject_loot_template` is empty");
}
void LoadLootTemplates_Item()
@@ -926,7 +926,7 @@ void LoadLootTemplates_Item()
if (count)
TC_LOG_INFO("server.loading", ">> Loaded %u item loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
else
- TC_LOG_ERROR("server.loading", ">> Loaded 0 item loot templates. DB table `item_loot_template` is empty");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 item loot templates. DB table `item_loot_template` is empty");
}
void LoadLootTemplates_Milling()
@@ -955,7 +955,7 @@ void LoadLootTemplates_Milling()
if (count)
TC_LOG_INFO("server.loading", ">> Loaded %u milling loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
else
- TC_LOG_ERROR("server.loading", ">> Loaded 0 milling loot templates. DB table `milling_loot_template` is empty");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 milling loot templates. DB table `milling_loot_template` is empty");
}
void LoadLootTemplates_Pickpocketing()
@@ -989,7 +989,7 @@ void LoadLootTemplates_Pickpocketing()
if (count)
TC_LOG_INFO("server.loading", ">> Loaded %u pickpocketing loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
else
- TC_LOG_ERROR("server.loading", ">> Loaded 0 pickpocketing loot templates. DB table `pickpocketing_loot_template` is empty");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 pickpocketing loot templates. DB table `pickpocketing_loot_template` is empty");
}
void LoadLootTemplates_Prospecting()
@@ -1018,7 +1018,7 @@ void LoadLootTemplates_Prospecting()
if (count)
TC_LOG_INFO("server.loading", ">> Loaded %u prospecting loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
else
- TC_LOG_ERROR("server.loading", ">> Loaded 0 prospecting loot templates. DB table `prospecting_loot_template` is empty");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 prospecting loot templates. DB table `prospecting_loot_template` is empty");
}
void LoadLootTemplates_Mail()
@@ -1042,7 +1042,7 @@ void LoadLootTemplates_Mail()
if (count)
TC_LOG_INFO("server.loading", ">> Loaded %u mail loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
else
- TC_LOG_ERROR("server.loading", ">> Loaded 0 mail loot templates. DB table `mail_loot_template` is empty");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 mail loot templates. DB table `mail_loot_template` is empty");
}
void LoadLootTemplates_Skinning()
@@ -1076,7 +1076,7 @@ void LoadLootTemplates_Skinning()
if (count)
TC_LOG_INFO("server.loading", ">> Loaded %u skinning loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
else
- TC_LOG_ERROR("server.loading", ">> Loaded 0 skinning loot templates. DB table `skinning_loot_template` is empty");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 skinning loot templates. DB table `skinning_loot_template` is empty");
}
void LoadLootTemplates_Spell()
@@ -1116,7 +1116,7 @@ void LoadLootTemplates_Spell()
if (count)
TC_LOG_INFO("server.loading", ">> Loaded %u spell loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
else
- TC_LOG_ERROR("server.loading", ">> Loaded 0 spell loot templates. DB table `spell_loot_template` is empty");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 spell loot templates. DB table `spell_loot_template` is empty");
}
void LoadLootTemplates_Reference()
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 0793422f8ad..61f24f2b6e5 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -23,6 +23,7 @@
#include "DisableMgr.h"
#include "DynamicTree.h"
#include "GameObjectModel.h"
+#include "GameTime.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "GridStates.h"
@@ -37,6 +38,7 @@
#include "ObjectGridLoader.h"
#include "ObjectMgr.h"
#include "Pet.h"
+#include "PoolMgr.h"
#include "ScriptMgr.h"
#include "Transport.h"
#include "Vehicle.h"
@@ -61,6 +63,10 @@ Map::~Map()
sScriptMgr->OnDestroyMap(this);
+ // Delete all waiting spawns, else there will be a memory leak
+ // This doesn't delete from database.
+ DeleteRespawnInfo();
+
while (!i_worldObjects.empty())
{
WorldObject* obj = *i_worldObjects.begin();
@@ -253,7 +259,7 @@ m_unloadTimer(0), m_VisibleDistance(DEFAULT_VISIBILITY_DISTANCE),
m_VisibilityNotifyPeriod(DEFAULT_VISIBILITY_NOTIFY_PERIOD),
m_activeNonPlayersIter(m_activeNonPlayers.end()), _transportsUpdateIter(_transports.end()),
i_gridExpiry(expiry),
-i_scriptLock(false), _defaultLight(GetDefaultMapLight(id))
+i_scriptLock(false), _respawnCheckTimer(0), _defaultLight(GetDefaultMapLight(id))
{
m_parentMap = (_parent ? _parent : this);
for (unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx)
@@ -266,6 +272,8 @@ i_scriptLock(false), _defaultLight(GetDefaultMapLight(id))
}
}
+ _zonePlayerCountMap.clear();
+
//lets initialize visibility distance for map
Map::InitVisibilityDistance();
@@ -522,6 +530,29 @@ bool Map::EnsureGridLoaded(Cell const& cell)
return false;
}
+void Map::GridMarkNoUnload(uint32 x, uint32 y)
+{
+ // First make sure this grid is loaded
+ float gX = ((float(x) - 0.5f - CENTER_GRID_ID) * SIZE_OF_GRIDS) + (CENTER_GRID_OFFSET * 2);
+ float gY = ((float(y) - 0.5f - CENTER_GRID_ID) * SIZE_OF_GRIDS) + (CENTER_GRID_OFFSET * 2);
+ Cell cell = Cell(gX, gY);
+ EnsureGridLoaded(cell);
+
+ // Mark as don't unload
+ NGridType* grid = getNGrid(x, y);
+ grid->setUnloadExplicitLock(true);
+}
+
+void Map::GridUnmarkNoUnload(uint32 x, uint32 y)
+{
+ // If grid is loaded, clear unload lock
+ if (IsGridLoaded(GridCoord(x, y)))
+ {
+ NGridType* grid = getNGrid(x, y);
+ grid->setUnloadExplicitLock(false);
+ }
+}
+
void Map::LoadGrid(float x, float y)
{
EnsureGridLoaded(Cell(x, y));
@@ -689,6 +720,21 @@ void Map::VisitNearbyCellsOf(WorldObject* obj, TypeContainerVisitor<Trinity::Obj
}
}
+void Map::UpdatePlayerZoneStats(uint32 oldZone, uint32 newZone)
+{
+ // Nothing to do if no change
+ if (oldZone == newZone)
+ return;
+
+ if (oldZone != MAP_INVALID_ZONE)
+ {
+ uint32& oldZoneCount = _zonePlayerCountMap[oldZone];
+ ASSERT(oldZoneCount, "A player left zone %u (went to %u) - but there were no players in the zone!", oldZone, newZone);
+ --oldZoneCount;
+ }
+ ++_zonePlayerCountMap[newZone];
+}
+
void Map::Update(uint32 t_diff)
{
_dynamicTree.update(t_diff);
@@ -704,6 +750,16 @@ void Map::Update(uint32 t_diff)
session->Update(t_diff, updater);
}
}
+
+ /// process any due respawns
+ if (_respawnCheckTimer <= t_diff)
+ {
+ ProcessRespawns();
+ _respawnCheckTimer = sWorld->getIntConfig(CONFIG_RESPAWN_MINCHECKINTERVALMS);
+ }
+ else
+ _respawnCheckTimer -= t_diff;
+
/// update active cells around players and active objects
resetMarkedCells();
@@ -885,6 +941,8 @@ void Map::ProcessRelocationNotifies(const uint32 diff)
void Map::RemovePlayerFromMap(Player* player, bool remove)
{
+ // Before leaving map, update zone/area for stats
+ player->UpdateZone(MAP_INVALID_ZONE, 0);
sScriptMgr->OnPlayerLeaveMap(this, player);
player->getHostileRefManager().deleteReferences(); // multithreading crashfix
@@ -2639,10 +2697,7 @@ void Map::GetFullTerrainStatusForPosition(float x, float y, float z, PositionFul
else
{
data.floorZ = mapHeight;
- if (gmap)
- data.areaId = gmap->getArea(x, y);
- else
- data.areaId = 0;
+ data.areaId = gmap->getArea(x, y);
if (!data.areaId)
data.areaId = i_mapEntry->linked_zone;
@@ -2744,11 +2799,6 @@ bool Map::getObjectHitPos(uint32 phasemask, float x1, float y1, float z1, float
return result;
}
-float Map::GetHeight(uint32 phasemask, float x, float y, float z, bool vmap/*=true*/, float maxSearchDist/*=DEFAULT_HEIGHT_SEARCH*/) const
-{
- return std::max<float>(GetHeight(x, y, z, vmap, maxSearchDist), GetGameObjectFloor(phasemask, x, y, z, maxSearchDist));
-}
-
bool Map::IsInWater(float x, float y, float pZ, LiquidData* data) const
{
LiquidData liquid_status;
@@ -2867,6 +2917,474 @@ void Map::SendObjectUpdates()
}
}
+bool Map::CheckRespawn(RespawnInfo* info)
+{
+ uint32 poolId = info->spawnId ? sPoolMgr->IsPartOfAPool(info->type, info->spawnId) : 0;
+ // First, check if there's already an instance of this object that would block the respawn
+ // Only do this for unpooled spawns
+ if (!poolId)
+ {
+ bool doDelete = false;
+ switch (info->type)
+ {
+ case SPAWN_TYPE_CREATURE:
+ {
+ // escort check for creatures only (if the world config boolean is set)
+ bool isEscort = false;
+ if (sWorld->getBoolConfig(CONFIG_RESPAWN_DYNAMIC_ESCORTNPC) && info->type == SPAWN_TYPE_CREATURE)
+ if (CreatureData const* cdata = sObjectMgr->GetCreatureData(info->spawnId))
+ if (cdata->spawnGroupData->flags & SPAWNGROUP_FLAG_ESCORTQUESTNPC)
+ isEscort = true;
+
+ auto range = _creatureBySpawnIdStore.equal_range(info->spawnId);
+ for (auto it = range.first; it != range.second; ++it)
+ {
+ Creature* creature = it->second;
+ if (!creature->IsAlive())
+ continue;
+ // escort NPCs are allowed to respawn as long as all other instances are already escorting
+ if (isEscort && creature->IsEscortNPC(true))
+ continue;
+ doDelete = true;
+ break;
+ }
+ break;
+ }
+ case SPAWN_TYPE_GAMEOBJECT:
+ // gameobject check is simpler - they cannot be dead or escorting
+ if (_gameobjectBySpawnIdStore.find(info->spawnId) != _gameobjectBySpawnIdStore.end())
+ doDelete = true;
+ break;
+ default:
+ ASSERT(false, "Invalid spawn type %u with spawnId %u on map %u", uint32(info->type), info->spawnId, GetId());
+ return true;
+ }
+ if (doDelete)
+ {
+ info->respawnTime = 0;
+ return false;
+ }
+ }
+
+ // next, check linked respawn time
+ ObjectGuid thisGUID = ObjectGuid((info->type == SPAWN_TYPE_GAMEOBJECT) ? HighGuid::GameObject : HighGuid::Unit, info->entry, info->spawnId);
+ if (time_t linkedTime = GetLinkedRespawnTime(thisGUID))
+ {
+ time_t now = time(NULL);
+ time_t respawnTime;
+ if (linkedTime == std::numeric_limits<time_t>::max())
+ respawnTime = linkedTime;
+ else if (sObjectMgr->GetLinkedRespawnGuid(thisGUID) == thisGUID) // never respawn, save "something" in DB
+ respawnTime = now + WEEK;
+ else // set us to check again shortly after linked unit
+ respawnTime = std::max<time_t>(now, linkedTime) + urand(5, 15);
+ info->respawnTime = respawnTime;
+ return false;
+ }
+
+ // now, check if we're part of a pool
+ if (poolId)
+ {
+ // ok, part of a pool - hand off to pool logic to handle this, we're just going to remove the respawn and call it a day
+ if (info->type == SPAWN_TYPE_GAMEOBJECT)
+ sPoolMgr->UpdatePool<GameObject>(poolId, info->spawnId);
+ else if (info->type == SPAWN_TYPE_CREATURE)
+ sPoolMgr->UpdatePool<Creature>(poolId, info->spawnId);
+ else
+ ASSERT(false, "Invalid spawn type %u (spawnid %u) on map %u", uint32(info->type), info->spawnId, GetId());
+ info->respawnTime = 0;
+ return false;
+ }
+
+ // if we're a creature, see if the script objects to us spawning
+ if (info->type == SPAWN_TYPE_CREATURE)
+ {
+ if (!sScriptMgr->CanSpawn(info->spawnId, info->entry, sObjectMgr->GetCreatureData(info->spawnId), this))
+ { // if a script blocks our respawn, schedule next check in a little bit
+ info->respawnTime = time(NULL) + urand(4, 7);
+ return false;
+ }
+ }
+ return true;
+}
+
+void Map::DoRespawn(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 gridId)
+{
+ if (!IsGridLoaded(gridId)) // if grid isn't loaded, this will be processed in grid load handler
+ return;
+
+ switch (type)
+ {
+ case SPAWN_TYPE_CREATURE:
+ {
+ Creature* obj = new Creature();
+ if (!obj->LoadFromDB(spawnId, this, true, true))
+ delete obj;
+ break;
+ }
+ case SPAWN_TYPE_GAMEOBJECT:
+ {
+ GameObject* obj = new GameObject();
+ if (!obj->LoadFromDB(spawnId, this, true))
+ delete obj;
+ break;
+ }
+ default:
+ ASSERT(false, "Invalid spawn type %u (spawnid %u) on map %u", uint32(type), spawnId, GetId());
+ }
+}
+
+void Map::Respawn(RespawnInfo* info, bool force, SQLTransaction dbTrans)
+{
+ if (!force && !CheckRespawn(info))
+ {
+ if (info->respawnTime)
+ SaveRespawnTime(info->type, info->spawnId, info->entry, info->respawnTime, info->zoneId, info->gridId, true, true, dbTrans);
+ else
+ RemoveRespawnTime(info);
+ return;
+ }
+
+ // remove the actual respawn record first - since this deletes it, we save what we need
+ SpawnObjectType const type = info->type;
+ uint32 const gridId = info->gridId;
+ ObjectGuid::LowType const spawnId = info->spawnId;
+ RemoveRespawnTime(info);
+ DoRespawn(type, spawnId, gridId);
+}
+
+void Map::Respawn(RespawnVector& respawnData, bool force, SQLTransaction dbTrans)
+{
+ SQLTransaction trans = dbTrans ? dbTrans : CharacterDatabase.BeginTransaction();
+ for (RespawnInfo* info : respawnData)
+ Respawn(info, force, trans);
+ if (!dbTrans)
+ CharacterDatabase.CommitTransaction(trans);
+}
+
+void Map::AddRespawnInfo(RespawnInfo& info, bool replace)
+{
+ if (!info.spawnId)
+ return;
+
+ RespawnInfoMap& bySpawnIdMap = GetRespawnMapForType(info.type);
+
+ auto it = bySpawnIdMap.find(info.spawnId);
+ if (it != bySpawnIdMap.end()) // spawnid already has a respawn scheduled
+ {
+ RespawnInfo* const existing = it->second;
+ if (replace || info.respawnTime < existing->respawnTime) // delete existing in this case
+ DeleteRespawnInfo(existing);
+ else // don't delete existing, instead replace respawn time so caller saves the correct time
+ {
+ info.respawnTime = existing->respawnTime;
+ return;
+ }
+ }
+
+ // if we get to this point, we should insert the respawninfo (there either was no prior entry, or it was deleted already)
+ RespawnInfo * ri = new RespawnInfo(info);
+ ri->handle = _respawnTimes.push(ri);
+ bool success = bySpawnIdMap.emplace(ri->spawnId, ri).second;
+ ASSERT(success, "Insertion of respawn info with id (%u,%u) into spawn id map failed - state desync.", uint32(ri->type), ri->spawnId);
+}
+
+static void PushRespawnInfoFrom(RespawnVector& data, RespawnInfoMap const& map, uint32 zoneId)
+{
+ for (auto const& pair : map)
+ if (!zoneId || pair.second->zoneId == zoneId)
+ data.push_back(pair.second);
+}
+void Map::GetRespawnInfo(RespawnVector& respawnData, SpawnObjectTypeMask types, uint32 zoneId) const
+{
+ if (types & SPAWN_TYPEMASK_CREATURE)
+ PushRespawnInfoFrom(respawnData, _creatureRespawnTimesBySpawnId, zoneId);
+ if (types & SPAWN_TYPEMASK_GAMEOBJECT)
+ PushRespawnInfoFrom(respawnData, _gameObjectRespawnTimesBySpawnId, zoneId);
+}
+
+RespawnInfo* Map::GetRespawnInfo(SpawnObjectType type, ObjectGuid::LowType spawnId) const
+{
+ RespawnInfoMap const& map = GetRespawnMapForType(type);
+ auto it = map.find(spawnId);
+ if (it == map.end())
+ return nullptr;
+ return it->second;
+}
+
+void Map::DeleteRespawnInfo() // delete everything
+{
+ for (RespawnInfo* info : _respawnTimes)
+ delete info;
+ _respawnTimes.clear();
+ _creatureRespawnTimesBySpawnId.clear();
+ _gameObjectRespawnTimesBySpawnId.clear();
+}
+
+void Map::DeleteRespawnInfo(RespawnInfo* info)
+{
+ // Delete from all relevant containers to ensure consistency
+ ASSERT(info);
+
+ // spawnid store
+ size_t const n = GetRespawnMapForType(info->type).erase(info->spawnId);
+ ASSERT(n == 1, "Respawn stores inconsistent for map %u, spawnid %u (type %u)", GetId(), info->spawnId, uint32(info->type));
+
+ //respawn heap
+ _respawnTimes.erase(info->handle);
+
+ // then cleanup the object
+ delete info;
+}
+
+void Map::RemoveRespawnTime(RespawnInfo* info, bool doRespawn, SQLTransaction dbTrans)
+{
+ PreparedStatement* stmt;
+ switch (info->type)
+ {
+ case SPAWN_TYPE_CREATURE:
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN);
+ break;
+ case SPAWN_TYPE_GAMEOBJECT:
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GO_RESPAWN);
+ break;
+ default:
+ ASSERT(false, "Invalid respawninfo type %u for spawnid %u map %u", uint32(info->type), info->spawnId, GetId());
+ return;
+ }
+ stmt->setUInt32(0, info->spawnId);
+ stmt->setUInt16(1, GetId());
+ stmt->setUInt32(2, GetInstanceId());
+ CharacterDatabase.ExecuteOrAppend(dbTrans, stmt);
+
+ if (doRespawn)
+ Respawn(info);
+ else
+ DeleteRespawnInfo(info);
+}
+
+void Map::RemoveRespawnTime(RespawnVector& respawnData, bool doRespawn, SQLTransaction dbTrans)
+{
+ SQLTransaction trans = dbTrans ? dbTrans : CharacterDatabase.BeginTransaction();
+ for (RespawnInfo* info : respawnData)
+ RemoveRespawnTime(info, doRespawn, trans);
+ if (!dbTrans)
+ CharacterDatabase.CommitTransaction(trans);
+}
+
+void Map::ProcessRespawns()
+{
+ time_t now = time(NULL);
+ while (!_respawnTimes.empty())
+ {
+ RespawnInfo* next = _respawnTimes.top();
+ if (now < next->respawnTime) // done for this tick
+ break;
+ if (CheckRespawn(next)) // see if we're allowed to respawn
+ {
+ // ok, respawn
+ _respawnTimes.pop();
+ GetRespawnMapForType(next->type).erase(next->spawnId);
+ DoRespawn(next->type, next->spawnId, next->gridId);
+ delete next;
+ }
+ else if (!next->respawnTime) // just remove respawn entry without rescheduling
+ {
+ _respawnTimes.pop();
+ GetRespawnMapForType(next->type).erase(next->spawnId);
+ delete next;
+ }
+ else // value changed, update heap position
+ {
+ ASSERT(now < next->respawnTime); // infinite loop guard
+ _respawnTimes.decrease(next->handle);
+ }
+ }
+}
+
+void Map::ApplyDynamicModeRespawnScaling(WorldObject const* obj, ObjectGuid::LowType spawnId, uint32& respawnDelay, uint32 mode) const
+{
+ ASSERT(mode == 1);
+ ASSERT(obj->GetMap() == this);
+
+ if (IsBattlegroundOrArena())
+ return;
+
+ SpawnObjectType type;
+ switch (obj->GetTypeId())
+ {
+ case TYPEID_UNIT:
+ type = SPAWN_TYPE_CREATURE;
+ break;
+ case TYPEID_GAMEOBJECT:
+ type = SPAWN_TYPE_GAMEOBJECT;
+ break;
+ default:
+ return;
+ }
+
+ SpawnData const* data = sObjectMgr->GetSpawnData(type, spawnId);
+ if (!data || !data->spawnGroupData || !(data->spawnGroupData->flags & SPAWNGROUP_FLAG_DYNAMIC_SPAWN_RATE))
+ return;
+
+ auto it = _zonePlayerCountMap.find(obj->GetZoneId());
+ if (it == _zonePlayerCountMap.end())
+ return;
+ uint32 const playerCount = it->second;
+ if (!playerCount)
+ return;
+ double const adjustFactor = sWorld->getFloatConfig(type == SPAWN_TYPE_GAMEOBJECT ? CONFIG_RESPAWN_DYNAMICRATE_GAMEOBJECT : CONFIG_RESPAWN_DYNAMICRATE_CREATURE) / playerCount;
+ if (adjustFactor >= 1.0) // nothing to do here
+ return;
+ uint32 const timeMinimum = sWorld->getIntConfig(type == SPAWN_TYPE_GAMEOBJECT ? CONFIG_RESPAWN_DYNAMICMINIMUM_GAMEOBJECT : CONFIG_RESPAWN_DYNAMICMINIMUM_CREATURE);
+ if (respawnDelay <= timeMinimum)
+ return;
+
+ respawnDelay = std::max<uint32>(ceil(respawnDelay * adjustFactor), timeMinimum);
+}
+
+SpawnGroupTemplateData const* Map::GetSpawnGroupData(uint32 groupId) const
+{
+ SpawnGroupTemplateData const* data = sObjectMgr->GetSpawnGroupData(groupId);
+ if (data && data->mapId == GetId())
+ return data;
+ return nullptr;
+}
+
+bool Map::SpawnGroupSpawn(uint32 groupId, bool ignoreRespawn, bool force, std::vector<WorldObject*>* spawnedObjects)
+{
+ SpawnGroupTemplateData const* groupData = GetSpawnGroupData(groupId);
+ if (!groupData || groupData->flags & SPAWNGROUP_FLAG_SYSTEM)
+ {
+ TC_LOG_ERROR("maps", "Tried to spawn non-existing (or system) spawn group %u on map %u. Blocked.", groupId, GetId());
+ return false;
+ }
+
+ for (auto& pair : sObjectMgr->GetSpawnDataForGroup(groupId))
+ {
+ SpawnData const* data = pair.second;
+ ASSERT(groupData->mapId == data->spawnPoint.GetMapId());
+ // Check if there's already an instance spawned
+ if (!force)
+ if (WorldObject* obj = GetWorldObjectBySpawnId(data->type, data->spawnId))
+ if ((data->type != SPAWN_TYPE_CREATURE) || obj->ToCreature()->IsAlive())
+ continue;
+
+ time_t respawnTime = GetRespawnTime(data->type, data->spawnId);
+ if (respawnTime && respawnTime > time(NULL))
+ {
+ if (!force && !ignoreRespawn)
+ continue;
+
+ // we need to remove the respawn time, otherwise we'd end up double spawning
+ RemoveRespawnTime(data->type, data->spawnId, false);
+ }
+
+ // don't spawn if the grid isn't loaded (will be handled in grid loader)
+ if (!IsGridLoaded(data->spawnPoint))
+ continue;
+
+ // Everything OK, now do the actual (re)spawn
+ switch (data->type)
+ {
+ case SPAWN_TYPE_CREATURE:
+ {
+ Creature* creature = new Creature();
+ if (!creature->LoadFromDB(data->spawnId, this, true, force))
+ delete creature;
+ else if (spawnedObjects)
+ spawnedObjects->push_back(creature);
+ break;
+ }
+ case SPAWN_TYPE_GAMEOBJECT:
+ {
+ GameObject* gameobject = new GameObject();
+ if (!gameobject->LoadFromDB(data->spawnId, this, true))
+ delete gameobject;
+ else if (spawnedObjects)
+ spawnedObjects->push_back(gameobject);
+ break;
+ }
+ default:
+ ASSERT(false, "Invalid spawn type %u with spawnId %u", uint32(data->type), data->spawnId);
+ return false;
+ }
+ }
+ SetSpawnGroupActive(groupId, true); // start processing respawns for the group
+ return true;
+}
+
+bool Map::SpawnGroupDespawn(uint32 groupId, bool deleteRespawnTimes)
+{
+ SpawnGroupTemplateData const* groupData = GetSpawnGroupData(groupId);
+ if (!groupData || groupData->flags & SPAWNGROUP_FLAG_SYSTEM)
+ {
+ TC_LOG_ERROR("maps", "Tried to despawn non-existing (or system) spawn group %u on map %u. Blocked.", groupId, GetId());
+ return false;
+ }
+
+ std::vector<WorldObject*> toUnload; // unload after iterating, otherwise iterator invalidation
+ for (auto const& pair : sObjectMgr->GetSpawnDataForGroup(groupId))
+ {
+ SpawnData const* data = pair.second;
+ ASSERT(groupData->mapId == data->spawnPoint.GetMapId());
+ if (deleteRespawnTimes)
+ RemoveRespawnTime(data->type, data->spawnId);
+ switch (data->type)
+ {
+ case SPAWN_TYPE_CREATURE:
+ {
+ auto bounds = GetCreatureBySpawnIdStore().equal_range(data->spawnId);
+ for (auto it = bounds.first; it != bounds.second; ++it)
+ toUnload.emplace_back(it->second);
+ break;
+ }
+ case SPAWN_TYPE_GAMEOBJECT:
+ {
+ auto bounds = GetGameObjectBySpawnIdStore().equal_range(data->spawnId);
+ for (auto it = bounds.first; it != bounds.second; ++it)
+ toUnload.emplace_back(it->second);
+ break;
+ }
+ default:
+ ASSERT(false, "Invalid spawn type %u in spawn data with spawnId %u.", uint32(data->type), data->spawnId);
+ return false;
+ }
+ }
+ // now do the actual despawning
+ for (WorldObject* obj : toUnload)
+ obj->AddObjectToRemoveList();
+ SetSpawnGroupActive(groupId, false); // stop processing respawns for the group, too
+ return true;
+}
+
+void Map::SetSpawnGroupActive(uint32 groupId, bool state)
+{
+ SpawnGroupTemplateData const* const data = GetSpawnGroupData(groupId);
+ if (!data || data->flags & SPAWNGROUP_FLAG_SYSTEM)
+ {
+ TC_LOG_ERROR("maps", "Tried to set non-existing (or system) spawn group %u to %s on map %u. Blocked.", groupId, state ? "active" : "inactive", GetId());
+ return;
+ }
+ if (state != !(data->flags & SPAWNGROUP_FLAG_MANUAL_SPAWN)) // toggled
+ _toggledSpawnGroupIds.insert(groupId);
+ else
+ _toggledSpawnGroupIds.erase(groupId);
+}
+
+bool Map::IsSpawnGroupActive(uint32 groupId) const
+{
+ SpawnGroupTemplateData const* const data = GetSpawnGroupData(groupId);
+ if (!data)
+ {
+ TC_LOG_WARN("maps", "Tried to query state of non-existing spawn group %u on map %u.", groupId, GetId());
+ return false;
+ }
+ if (data->flags & SPAWNGROUP_FLAG_SYSTEM)
+ return true;
+ return (_toggledSpawnGroupIds.find(groupId) != _toggledSpawnGroupIds.end()) != !(data->flags & SPAWNGROUP_FLAG_MANUAL_SPAWN);
+}
+
void Map::DelayedUpdate(uint32 t_diff)
{
for (_transportsUpdateIter = _transports.begin(); _transportsUpdateIter != _transports.end();)
@@ -3364,6 +3882,8 @@ void InstanceMap::CreateInstanceData(bool load)
}
}
}
+ else
+ i_data->Create();
}
/*
@@ -3693,6 +4213,34 @@ Creature* Map::GetCreature(ObjectGuid const& guid)
return _objectsStore.Find<Creature>(guid);
}
+Creature* Map::GetCreatureBySpawnId(ObjectGuid::LowType spawnId) const
+{
+ auto const bounds = GetCreatureBySpawnIdStore().equal_range(spawnId);
+ if (bounds.first == bounds.second)
+ return nullptr;
+
+ std::unordered_multimap<uint32, Creature*>::const_iterator creatureItr = std::find_if(bounds.first, bounds.second, [](Map::CreatureBySpawnIdContainer::value_type const& pair)
+ {
+ return pair.second->IsAlive();
+ });
+
+ return creatureItr != bounds.second ? creatureItr->second : bounds.first->second;
+}
+
+GameObject* Map::GetGameObjectBySpawnId(ObjectGuid::LowType spawnId) const
+{
+ auto const bounds = GetGameObjectBySpawnIdStore().equal_range(spawnId);
+ if (bounds.first == bounds.second)
+ return nullptr;
+
+ std::unordered_multimap<uint32, GameObject*>::const_iterator creatureItr = std::find_if(bounds.first, bounds.second, [](Map::GameObjectBySpawnIdContainer::value_type const& pair)
+ {
+ return pair.second->isSpawned();
+ });
+
+ return creatureItr != bounds.second ? creatureItr->second : bounds.first->second;
+}
+
GameObject* Map::GetGameObject(ObjectGuid const& guid)
{
return _objectsStore.Find<GameObject>(guid);
@@ -3723,64 +4271,37 @@ void Map::UpdateIteratorBack(Player* player)
m_mapRefIter = m_mapRefIter->nocheck_prev();
}
-void Map::SaveCreatureRespawnTime(ObjectGuid::LowType dbGuid, time_t respawnTime)
+void Map::SaveRespawnTime(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 entry, time_t respawnTime, uint32 zoneId, uint32 gridId, bool writeDB, bool replace, SQLTransaction dbTrans)
{
if (!respawnTime)
{
// Delete only
- RemoveCreatureRespawnTime(dbGuid);
+ RemoveRespawnTime(type, spawnId, false, dbTrans);
return;
}
- _creatureRespawnTimes[dbGuid] = respawnTime;
+ RespawnInfo ri;
+ ri.type = type;
+ ri.spawnId = spawnId;
+ ri.entry = entry;
+ ri.respawnTime = respawnTime;
+ ri.gridId = gridId;
+ ri.zoneId = zoneId;
+ AddRespawnInfo(ri, replace);
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_CREATURE_RESPAWN);
- stmt->setUInt32(0, dbGuid);
- stmt->setUInt64(1, uint64(respawnTime));
- stmt->setUInt16(2, GetId());
- stmt->setUInt32(3, GetInstanceId());
- CharacterDatabase.Execute(stmt);
+ if (writeDB)
+ SaveRespawnTimeDB(type, spawnId, ri.respawnTime, dbTrans); // might be different from original respawn time if we didn't replace
}
-void Map::RemoveCreatureRespawnTime(ObjectGuid::LowType dbGuid)
+void Map::SaveRespawnTimeDB(SpawnObjectType type, ObjectGuid::LowType spawnId, time_t respawnTime, SQLTransaction dbTrans)
{
- _creatureRespawnTimes.erase(dbGuid);
-
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN);
- stmt->setUInt32(0, dbGuid);
- stmt->setUInt16(1, GetId());
- stmt->setUInt32(2, GetInstanceId());
- CharacterDatabase.Execute(stmt);
-}
-
-void Map::SaveGORespawnTime(ObjectGuid::LowType dbGuid, time_t respawnTime)
-{
- if (!respawnTime)
- {
- // Delete only
- RemoveGORespawnTime(dbGuid);
- return;
- }
-
- _goRespawnTimes[dbGuid] = respawnTime;
-
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GO_RESPAWN);
- stmt->setUInt32(0, dbGuid);
+ // Just here for support of compatibility mode
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement((type == SPAWN_TYPE_GAMEOBJECT) ? CHAR_REP_GO_RESPAWN : CHAR_REP_CREATURE_RESPAWN);
+ stmt->setUInt32(0, spawnId);
stmt->setUInt64(1, uint64(respawnTime));
stmt->setUInt16(2, GetId());
stmt->setUInt32(3, GetInstanceId());
- CharacterDatabase.Execute(stmt);
-}
-
-void Map::RemoveGORespawnTime(ObjectGuid::LowType dbGuid)
-{
- _goRespawnTimes.erase(dbGuid);
-
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GO_RESPAWN);
- stmt->setUInt32(0, dbGuid);
- stmt->setUInt16(1, GetId());
- stmt->setUInt32(2, GetInstanceId());
- CharacterDatabase.Execute(stmt);
+ CharacterDatabase.ExecuteOrAppend(dbTrans, stmt);
}
void Map::LoadRespawnTimes()
@@ -3796,7 +4317,9 @@ void Map::LoadRespawnTimes()
ObjectGuid::LowType loguid = fields[0].GetUInt32();
uint64 respawnTime = fields[1].GetUInt64();
- _creatureRespawnTimes[loguid] = time_t(respawnTime);
+ if (CreatureData const* cdata = sObjectMgr->GetCreatureData(loguid))
+ SaveRespawnTime(SPAWN_TYPE_CREATURE, loguid, cdata->id, time_t(respawnTime), GetZoneId(cdata->spawnPoint), Trinity::ComputeGridCoord(cdata->spawnPoint.GetPositionX(), cdata->spawnPoint.GetPositionY()).GetId(), false);
+
} while (result->NextRow());
}
@@ -3811,19 +4334,13 @@ void Map::LoadRespawnTimes()
ObjectGuid::LowType loguid = fields[0].GetUInt32();
uint64 respawnTime = fields[1].GetUInt64();
- _goRespawnTimes[loguid] = time_t(respawnTime);
+ if (GameObjectData const* godata = sObjectMgr->GetGameObjectData(loguid))
+ SaveRespawnTime(SPAWN_TYPE_GAMEOBJECT, loguid, godata->id, time_t(respawnTime), GetZoneId(godata->spawnPoint), Trinity::ComputeGridCoord(godata->spawnPoint.GetPositionX(), godata->spawnPoint.GetPositionY()).GetId(), false);
+
} while (result->NextRow());
}
}
-void Map::DeleteRespawnTimes()
-{
- _creatureRespawnTimes.clear();
- _goRespawnTimes.clear();
-
- DeleteRespawnTimesInDB(GetId(), GetInstanceId());
-}
-
void Map::DeleteRespawnTimesInDB(uint16 mapId, uint32 instanceId)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN_BY_INSTANCE);
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index dd0e43158c1..3d3fcfb528d 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -21,16 +21,18 @@
#include "Define.h"
-#include "GridDefines.h"
#include "Cell.h"
-#include "Timer.h"
-#include "SharedDefines.h"
+#include "DynamicTree.h"
+#include "GridDefines.h"
#include "GridRefManager.h"
#include "MapRefManager.h"
-#include "DynamicTree.h"
#include "ObjectGuid.h"
#include "Optional.h"
-
+#include "SharedDefines.h"
+#include "SpawnData.h"
+#include "Timer.h"
+#include "Transaction.h"
+#include <boost/heap/fibonacci_heap.hpp>
#include <bitset>
#include <list>
#include <memory>
@@ -268,10 +270,41 @@ struct ZoneDynamicInfo
#define MAX_FALL_DISTANCE 250000.0f // "unlimited fall" to find VMap ground if it is available, just larger than MAX_HEIGHT - INVALID_HEIGHT
#define DEFAULT_HEIGHT_SEARCH 50.0f // default search distance to find height at nearby locations
#define MIN_UNLOAD_DELAY 1 // immediate unload
+#define MAP_INVALID_ZONE 0xFFFFFFFF
typedef std::map<uint32/*leaderDBGUID*/, CreatureGroup*> CreatureGroupHolderType;
+struct RespawnInfo; // forward declaration
+struct CompareRespawnInfo
+{
+ bool operator()(RespawnInfo const* a, RespawnInfo const* b) const;
+};
typedef std::unordered_map<uint32 /*zoneId*/, ZoneDynamicInfo> ZoneDynamicInfoMap;
+typedef boost::heap::fibonacci_heap<RespawnInfo*, boost::heap::compare<CompareRespawnInfo>> RespawnListContainer;
+typedef RespawnListContainer::handle_type RespawnListHandle;
+typedef std::unordered_map<uint32, RespawnInfo*> RespawnInfoMap;
+typedef std::vector<RespawnInfo*> RespawnVector;
+struct RespawnInfo
+{
+ SpawnObjectType type;
+ ObjectGuid::LowType spawnId;
+ uint32 entry;
+ time_t respawnTime;
+ uint32 gridId;
+ uint32 zoneId;
+ RespawnListHandle handle;
+};
+inline bool CompareRespawnInfo::operator()(RespawnInfo const* a, RespawnInfo const* b) const
+{
+ if (a == b)
+ return false;
+ if (a->respawnTime != b->respawnTime)
+ return (a->respawnTime > b->respawnTime);
+ if (a->spawnId != b->spawnId)
+ return a->spawnId < b->spawnId;
+ ASSERT(a->type != b->type, "Duplicate respawn entry for spawnId (%u,%u) found!", a->type, a->spawnId);
+ return a->type < b->type;
+}
class TC_GAME_API Map : public GridRefManager<NGridType>
{
@@ -321,17 +354,19 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
GridCoord p = Trinity::ComputeGridCoord(x, y);
return !getNGrid(p.x_coord, p.y_coord) || getNGrid(p.x_coord, p.y_coord)->GetGridState() == GRID_STATE_REMOVAL;
}
+ bool IsRemovalGrid(Position const& pos) const { return IsRemovalGrid(pos.GetPositionX(), pos.GetPositionY()); }
- bool IsGridLoaded(float x, float y) const
- {
- return IsGridLoaded(Trinity::ComputeGridCoord(x, y));
- }
+ bool IsGridLoaded(uint32 gridId) const { return IsGridLoaded(GridCoord(gridId % MAX_NUMBER_OF_GRIDS, gridId / MAX_NUMBER_OF_GRIDS)); }
+ bool IsGridLoaded(float x, float y) const { return IsGridLoaded(Trinity::ComputeGridCoord(x, y)); }
+ bool IsGridLoaded(Position const& pos) const { return IsGridLoaded(pos.GetPositionX(), pos.GetPositionY()); }
bool GetUnloadLock(GridCoord const& p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadLock(); }
void SetUnloadLock(GridCoord const& p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadExplicitLock(on); }
void LoadGrid(float x, float y);
void LoadAllCells();
bool UnloadGrid(NGridType& ngrid, bool pForce);
+ void GridMarkNoUnload(uint32 x, uint32 y);
+ void GridUnmarkNoUnload(uint32 x, uint32 y);
virtual void UnloadAll();
void ResetGridExpiry(NGridType &grid, float factor = 1) const
@@ -350,18 +385,16 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
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 checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const;
- float GetMinHeight(float x, float y) const;
-
void GetFullTerrainStatusForPosition(float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType = MAP_ALL_LIQUIDS) const;
ZLiquidStatus GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = nullptr) const;
bool GetAreaInfo(float x, float y, float z, uint32& mogpflags, int32& adtId, int32& rootId, int32& groupId) const;
uint32 GetAreaId(float x, float y, float z, bool *isOutdoors = nullptr) const;
+ uint32 GetAreaId(Position const& pos) const { return GetAreaId(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); }
uint32 GetZoneId(float x, float y, float z) const;
+ uint32 GetZoneId(Position const& pos) const { return GetZoneId(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); }
void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const;
+ void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, Position const& pos) const { GetZoneAndAreaId(zoneid, areaid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); }
bool IsOutdoors(float x, float y, float z) const;
@@ -464,6 +497,9 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
Corpse* GetCorpse(ObjectGuid const& guid);
Creature* GetCreature(ObjectGuid const& guid);
GameObject* GetGameObject(ObjectGuid const& guid);
+ Creature* GetCreatureBySpawnId(ObjectGuid::LowType spawnId) const;
+ GameObject* GetGameObjectBySpawnId(ObjectGuid::LowType spawnId) const;
+ WorldObject* GetWorldObjectBySpawnId(SpawnObjectType type, ObjectGuid::LowType spawnId) const { return (type == SPAWN_TYPE_GAMEOBJECT) ? reinterpret_cast<WorldObject*>(GetGameObjectBySpawnId(spawnId)) : reinterpret_cast<WorldObject*>(GetCreatureBySpawnId(spawnId)); }
Transport* GetTransport(ObjectGuid const& guid);
DynamicObject* GetDynamicObject(ObjectGuid const& guid);
Pet* GetPet(ObjectGuid const& guid);
@@ -472,9 +508,11 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
typedef std::unordered_multimap<ObjectGuid::LowType, Creature*> CreatureBySpawnIdContainer;
CreatureBySpawnIdContainer& GetCreatureBySpawnIdStore() { return _creatureBySpawnIdStore; }
+ CreatureBySpawnIdContainer const& GetCreatureBySpawnIdStore() const { return _creatureBySpawnIdStore; }
typedef std::unordered_multimap<ObjectGuid::LowType, GameObject*> GameObjectBySpawnIdContainer;
GameObjectBySpawnIdContainer& GetGameObjectBySpawnIdStore() { return _gameobjectBySpawnIdStore; }
+ GameObjectBySpawnIdContainer const& GetGameObjectBySpawnIdStore() const { return _gameobjectBySpawnIdStore; }
std::unordered_set<Corpse*> const* GetCorpsesInCell(uint32 cellId) const
{
@@ -504,7 +542,11 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
BattlegroundMap const* ToBattlegroundMap() const { if (IsBattlegroundOrArena()) return reinterpret_cast<BattlegroundMap const*>(this); return nullptr; }
float GetWaterOrGroundLevel(uint32 phasemask, float x, float y, float z, float* ground = nullptr, bool swim = false) const;
- float GetHeight(uint32 phasemask, float x, float y, float z, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const;
+ float GetMinHeight(float x, float y) const;
+ float GetHeight(float x, float y, float z, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const;
+ float GetHeight(Position const& pos, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const { return GetHeight(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), vmap, maxSearchDist); }
+ float GetHeight(uint32 phasemask, float x, float y, float z, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const { return std::max<float>(GetHeight(x, y, z, vmap, maxSearchDist), GetGameObjectFloor(phasemask, x, y, z, maxSearchDist)); }
+ float GetHeight(uint32 phasemask, Position const& pos, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const { return GetHeight(phasemask, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), vmap, maxSearchDist); }
bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask, LineOfSightChecks checks, VMAP::ModelIgnoreFlags ignoreFlags) const;
void Balance() { _dynamicTree.balance(); }
void RemoveGameObjectModel(GameObjectModel const& model) { _dynamicTree.remove(model); }
@@ -522,28 +564,24 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
time_t GetLinkedRespawnTime(ObjectGuid guid) const;
time_t GetCreatureRespawnTime(ObjectGuid::LowType dbGuid) const
{
- std::unordered_map<ObjectGuid::LowType /*dbGUID*/, time_t>::const_iterator itr = _creatureRespawnTimes.find(dbGuid);
- if (itr != _creatureRespawnTimes.end())
- return itr->second;
-
- return time_t(0);
+ RespawnInfoMap::const_iterator itr = _creatureRespawnTimesBySpawnId.find(dbGuid);
+ return itr != _creatureRespawnTimesBySpawnId.end() ? itr->second->respawnTime : 0;
}
time_t GetGORespawnTime(ObjectGuid::LowType dbGuid) const
{
- std::unordered_map<ObjectGuid::LowType /*dbGUID*/, time_t>::const_iterator itr = _goRespawnTimes.find(dbGuid);
- if (itr != _goRespawnTimes.end())
- return itr->second;
-
- return time_t(0);
+ RespawnInfoMap::const_iterator itr = _gameObjectRespawnTimesBySpawnId.find(dbGuid);
+ return itr != _gameObjectRespawnTimesBySpawnId.end() ? itr->second->respawnTime : 0;
}
- void SaveCreatureRespawnTime(ObjectGuid::LowType dbGuid, time_t respawnTime);
- void RemoveCreatureRespawnTime(ObjectGuid::LowType dbGuid);
- void SaveGORespawnTime(ObjectGuid::LowType dbGuid, time_t respawnTime);
- void RemoveGORespawnTime(ObjectGuid::LowType dbGuid);
+ time_t GetRespawnTime(SpawnObjectType type, ObjectGuid::LowType spawnId) const { return (type == SPAWN_TYPE_GAMEOBJECT) ? GetGORespawnTime(spawnId) : GetCreatureRespawnTime(spawnId); }
+
+ void UpdatePlayerZoneStats(uint32 oldZone, uint32 newZone);
+
+ void SaveRespawnTime(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 entry, time_t respawnTime, uint32 zoneId, uint32 gridId = 0, bool writeDB = true, bool replace = false, SQLTransaction dbTrans = nullptr);
+ void SaveRespawnTimeDB(SpawnObjectType type, ObjectGuid::LowType spawnId, time_t respawnTime, SQLTransaction dbTrans = nullptr);
void LoadRespawnTimes();
- void DeleteRespawnTimes();
+ void DeleteRespawnTimes() { DeleteRespawnInfo(); DeleteRespawnTimesInDB(GetId(), GetInstanceId()); }
void LoadCorpseData();
void DeleteCorpseData();
@@ -702,6 +740,65 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
typedef std::multimap<time_t, ScriptAction> ScriptScheduleMap;
ScriptScheduleMap m_scriptSchedule;
+ public:
+ void ProcessRespawns();
+ void ApplyDynamicModeRespawnScaling(WorldObject const* obj, ObjectGuid::LowType spawnId, uint32& respawnDelay, uint32 mode) const;
+
+ private:
+ // if return value is true, we can respawn
+ // if return value is false, reschedule the respawn to new value of info->respawnTime iff nonzero, delete otherwise
+ // if return value is false and info->respawnTime is nonzero, it is guaranteed to be greater than time(NULL)
+ bool CheckRespawn(RespawnInfo* info);
+ void DoRespawn(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 gridId);
+ void Respawn(RespawnInfo* info, bool force = false, SQLTransaction dbTrans = nullptr);
+ void Respawn(RespawnVector& respawnData, bool force = false, SQLTransaction dbTrans = nullptr);
+ void AddRespawnInfo(RespawnInfo& info, bool replace = false);
+ void DeleteRespawnInfo();
+ void DeleteRespawnInfo(RespawnInfo* info);
+ void DeleteRespawnInfo(RespawnVector& toDelete)
+ {
+ for (RespawnInfo* info : toDelete)
+ DeleteRespawnInfo(info);
+ toDelete.clear();
+ }
+ void DeleteRespawnInfo(SpawnObjectTypeMask types, uint32 zoneId = 0)
+ {
+ RespawnVector v;
+ GetRespawnInfo(v, types, zoneId);
+ if (!v.empty())
+ DeleteRespawnInfo(v);
+ }
+ void DeleteRespawnInfo(SpawnObjectType type, ObjectGuid::LowType spawnId)
+ {
+ if (RespawnInfo* info = GetRespawnInfo(type, spawnId))
+ DeleteRespawnInfo(info);
+ }
+
+ public:
+ void GetRespawnInfo(RespawnVector& respawnData, SpawnObjectTypeMask types, uint32 zoneId = 0) const;
+ RespawnInfo* GetRespawnInfo(SpawnObjectType type, ObjectGuid::LowType spawnId) const;
+ void RemoveRespawnTime(RespawnInfo* info, bool doRespawn = false, SQLTransaction dbTrans = nullptr);
+ void RemoveRespawnTime(RespawnVector& respawnData, bool doRespawn = false, SQLTransaction dbTrans = nullptr);
+ void RemoveRespawnTime(SpawnObjectTypeMask types = SPAWN_TYPEMASK_ALL, uint32 zoneId = 0, bool doRespawn = false, SQLTransaction dbTrans = nullptr)
+ {
+ RespawnVector v;
+ GetRespawnInfo(v, types, zoneId);
+ if (!v.empty())
+ RemoveRespawnTime(v, doRespawn, dbTrans);
+ }
+ void RemoveRespawnTime(SpawnObjectType type, ObjectGuid::LowType spawnId, bool doRespawn = false, SQLTransaction dbTrans = nullptr)
+ {
+ if (RespawnInfo* info = GetRespawnInfo(type, spawnId))
+ RemoveRespawnTime(info, doRespawn, dbTrans);
+ }
+
+ SpawnGroupTemplateData const* GetSpawnGroupData(uint32 groupId) const;
+ bool SpawnGroupSpawn(uint32 groupId, bool ignoreRespawn = false, bool force = false, std::vector<WorldObject*>* spawnedObjects = nullptr);
+ bool SpawnGroupDespawn(uint32 groupId, bool deleteRespawnTimes = false);
+ void SetSpawnGroupActive(uint32 groupId, bool state);
+ bool IsSpawnGroupActive(uint32 groupId) const;
+
+ private:
// Type specific code for add/remove to/from grid
template<class T>
void AddToGrid(T* object, Cell const& cell);
@@ -730,8 +827,15 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
m_activeNonPlayers.erase(obj);
}
- std::unordered_map<ObjectGuid::LowType /*dbGUID*/, time_t> _creatureRespawnTimes;
- std::unordered_map<ObjectGuid::LowType /*dbGUID*/, time_t> _goRespawnTimes;
+ RespawnListContainer _respawnTimes;
+ RespawnInfoMap _creatureRespawnTimesBySpawnId;
+ RespawnInfoMap _gameObjectRespawnTimesBySpawnId;
+ RespawnInfoMap& GetRespawnMapForType(SpawnObjectType type) { return (type == SPAWN_TYPE_GAMEOBJECT) ? _gameObjectRespawnTimesBySpawnId : _creatureRespawnTimesBySpawnId; }
+ RespawnInfoMap const& GetRespawnMapForType(SpawnObjectType type) const { return (type == SPAWN_TYPE_GAMEOBJECT) ? _gameObjectRespawnTimesBySpawnId : _creatureRespawnTimesBySpawnId; }
+ std::unordered_set<uint32> _toggledSpawnGroupIds;
+
+ uint32 _respawnCheckTimer;
+ std::unordered_map<uint32, uint32> _zonePlayerCountMap;
ZoneDynamicInfoMap _zoneDynamicInfo;
uint32 _defaultLight;
diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h
index e628a7030ae..96147c7ded7 100644
--- a/src/server/game/Maps/MapManager.h
+++ b/src/server/game/Maps/MapManager.h
@@ -44,16 +44,22 @@ class TC_GAME_API MapManager
Map const* m = const_cast<MapManager*>(this)->CreateBaseMap(mapid);
return m->GetAreaId(x, y, z);
}
+ uint32 GetAreaId(uint32 mapid, Position const& pos) const { return GetAreaId(mapid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); }
+ uint32 GetAreaId(WorldLocation const& loc) const { return GetAreaId(loc.GetMapId(), loc); }
uint32 GetZoneId(uint32 mapid, float x, float y, float z) const
{
Map const* m = const_cast<MapManager*>(this)->CreateBaseMap(mapid);
return m->GetZoneId(x, y, z);
}
- void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, uint32 mapid, float x, float y, float z)
+ uint32 GetZoneId(uint32 mapid, Position const& pos) const { return GetZoneId(mapid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); }
+ uint32 GetZoneId(WorldLocation const& loc) const { return GetZoneId(loc.GetMapId(), loc); }
+ void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, uint32 mapid, float x, float y, float z) const
{
Map const* m = const_cast<MapManager*>(this)->CreateBaseMap(mapid);
m->GetZoneAndAreaId(zoneid, areaid, x, y, z);
}
+ void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, uint32 mapid, Position const& pos) const { GetZoneAndAreaId(zoneid, areaid, mapid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); }
+ void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, WorldLocation const& loc) const { GetZoneAndAreaId(zoneid, areaid, loc.GetMapId(), loc); }
void Initialize(void);
void Update(uint32);
diff --git a/src/server/game/Maps/MapScripts.cpp b/src/server/game/Maps/MapScripts.cpp
index e365a54c594..20ebc1db460 100644
--- a/src/server/game/Maps/MapScripts.cpp
+++ b/src/server/game/Maps/MapScripts.cpp
@@ -671,7 +671,7 @@ void Map::ScriptsProcess()
Unit* uSource = nullptr;
Unit* uTarget = nullptr;
- // source/target cast spell at target/source (script->datalong2: 0: s->t 1: s->s 2: t->t 3: t->s
+ // source/target cast spell at target/source (script->datalong2: 0: s->t 1: s->s 2: t->t 3: t->s)
switch (step.script->CastSpell.Flags)
{
case SF_CASTSPELL_SOURCE_TO_TARGET: // source -> target
diff --git a/src/server/game/Maps/SpawnData.h b/src/server/game/Maps/SpawnData.h
new file mode 100644
index 00000000000..768d1fd26bd
--- /dev/null
+++ b/src/server/game/Maps/SpawnData.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TRINITY_SPAWNDATA_H
+#define TRINITY_SPAWNDATA_H
+
+#include "Position.h"
+
+enum SpawnObjectType
+{
+ SPAWN_TYPE_CREATURE = 0,
+ SPAWN_TYPE_GAMEOBJECT = 1,
+
+ SPAWN_TYPE_MAX
+};
+
+enum SpawnObjectTypeMask
+{
+ SPAWN_TYPEMASK_CREATURE = (1 << SPAWN_TYPE_CREATURE),
+ SPAWN_TYPEMASK_GAMEOBJECT = (1 << SPAWN_TYPE_GAMEOBJECT),
+
+ SPAWN_TYPEMASK_ALL = (1 << SPAWN_TYPE_MAX)-1
+};
+
+enum SpawnGroupFlags
+{
+ SPAWNGROUP_FLAG_NONE = 0x00,
+ SPAWNGROUP_FLAG_SYSTEM = 0x01,
+ SPAWNGROUP_FLAG_COMPATIBILITY_MODE = 0x02,
+ SPAWNGROUP_FLAG_MANUAL_SPAWN = 0x04,
+ SPAWNGROUP_FLAG_DYNAMIC_SPAWN_RATE = 0x08,
+ SPAWNGROUP_FLAG_ESCORTQUESTNPC = 0x10,
+
+ SPAWNGROUP_FLAGS_ALL = (SPAWNGROUP_FLAG_SYSTEM | SPAWNGROUP_FLAG_COMPATIBILITY_MODE | SPAWNGROUP_FLAG_MANUAL_SPAWN | SPAWNGROUP_FLAG_DYNAMIC_SPAWN_RATE | SPAWNGROUP_FLAG_ESCORTQUESTNPC)
+};
+
+struct SpawnGroupTemplateData
+{
+ uint32 groupId;
+ std::string name;
+ uint32 mapId;
+ SpawnGroupFlags flags;
+};
+
+struct SpawnData
+{
+ SpawnObjectType const type;
+ uint32 spawnId = 0;
+ uint32 id = 0; // entry in respective _template table
+ WorldLocation spawnPoint;
+ uint32 phaseMask = 0;
+ int32 spawntimesecs = 0;
+ uint8 spawnMask = 0;
+ SpawnGroupTemplateData const* spawnGroupData = nullptr;
+ uint32 scriptId = 0;
+ bool dbData = true;
+
+ protected:
+ SpawnData(SpawnObjectType t) : type(t) {}
+};
+
+#endif
diff --git a/src/server/game/Miscellaneous/Formulas.h b/src/server/game/Miscellaneous/Formulas.h
index 81e906ed47d..7931860868e 100644
--- a/src/server/game/Miscellaneous/Formulas.h
+++ b/src/server/game/Miscellaneous/Formulas.h
@@ -158,6 +158,13 @@ namespace Trinity
baseGain = 0;
}
+ if (sWorld->getIntConfig(CONFIG_MIN_CREATURE_SCALED_XP_RATIO))
+ {
+ // Use mob level instead of player level to avoid overscaling on gain in a min is enforced
+ uint32 baseGainMin = (mob_level * 5 + nBaseExp) * sWorld->getIntConfig(CONFIG_MIN_CREATURE_SCALED_XP_RATIO) / 100;
+ baseGain = std::max(baseGainMin, baseGain);
+ }
+
sScriptMgr->OnBaseGainCalculation(baseGain, pl_level, mob_level, content);
return baseGain;
}
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
index d96b33fd968..400685c1c1b 100644
--- a/src/server/game/Miscellaneous/Language.h
+++ b/src/server/game/Miscellaneous/Language.h
@@ -1147,7 +1147,32 @@ enum TrinityStrings
LANG_COMMAND_MUTEHISTORY_EMPTY = 5060,
LANG_COMMAND_MUTEHISTORY_OUTPUT = 5061,
- // Room for more Trinity strings 5062-9999
+ // Scene debugs commands [Master only, not used in 3.3.5]
+ /*LANG_COMMAND_SCENE_DEBUG_ON = 5062,
+ LANG_COMMAND_SCENE_DEBUG_OFF = 5063,
+ LANG_COMMAND_SCENE_DEBUG_PLAY = 5064,
+ LANG_COMMAND_SCENE_DEBUG_TRIGGER = 5065,
+ LANG_COMMAND_SCENE_DEBUG_CANCEL = 5066,
+ LANG_COMMAND_SCENE_DEBUG_COMPLETE = 5067,
+ LANG_DEBUG_SCENE_OBJECT_LIST = 5068,
+ LANG_DEBUG_SCENE_OBJECT_DETAIL = 5069, */
+
+ // Strings added for dynamic_spawning
+ LANG_SPAWNINFO_GROUP_ID = 5070,
+ LANG_SPAWNINFO_COMPATIBILITY_MODE = 5071,
+ LANG_SPAWNINFO_GUIDINFO = 5072,
+ LANG_SPAWNINFO_SPAWNID_LOCATION = 5073,
+ LANG_SPAWNINFO_DISTANCEFROMPLAYER = 5074,
+ LANG_SPAWNGROUP_BADGROUP = 5075,
+ LANG_SPAWNGROUP_SPAWNCOUNT = 5076,
+ LANG_LIST_RESPAWNS_RANGE = 5077,
+ LANG_LIST_RESPAWNS_ZONE = 5078,
+ LANG_LIST_RESPAWNS_LISTHEADER = 5079,
+ LANG_LIST_RESPAWNS_OVERDUE = 5080,
+ LANG_LIST_RESPAWNS_CREATURES = 5081,
+ LANG_LIST_RESPAWNS_GAMEOBJECTS = 5082,
+
+ // Room for more Trinity strings 5084-6603
// Level requirement notifications
LANG_SAY_REQ = 6604,
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 7ea78f14ca4..d6bea21f2ad 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -1443,7 +1443,7 @@ enum Targets
TARGET_DEST_CHANNEL_CASTER = 106,
TARGET_UNK_DEST_AREA_UNK_107 = 107, // not enough info - only generic spells avalible
TARGET_GAMEOBJECT_CONE = 108,
- TARGET_DEST_UNK_110 = 110, // 1 spell
+ TARGET_UNIT_CONE_ENTRY_110 = 110, // 1 spell
TOTAL_SPELL_TARGETS
};
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp
index 6e771a29979..3f77e472189 100644
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -17,25 +17,28 @@
*/
#include "MotionMaster.h"
+#include "ConfusedMovementGenerator.h"
#include "Creature.h"
#include "CreatureAISelector.h"
#include "DBCStores.h"
-#include "Log.h"
-#include "Map.h"
-#include "PathGenerator.h"
-#include "ScriptSystem.h"
-#include "ConfusedMovementGenerator.h"
#include "FleeingMovementGenerator.h"
+#include "FormationMovementGenerator.h"
#include "HomeMovementGenerator.h"
#include "IdleMovementGenerator.h"
+#include "Log.h"
+#include "Map.h"
+#include "MoveSpline.h"
+#include "MoveSplineInit.h"
+#include "PathGenerator.h"
+#include "Player.h"
#include "PointMovementGenerator.h"
-#include "TargetedMovementGenerator.h"
-#include "WaypointMovementGenerator.h"
#include "RandomMovementGenerator.h"
+#include "ScriptSystem.h"
#include "SplineChainMovementGenerator.h"
-#include "FormationMovementGenerator.h"
-#include "MoveSpline.h"
-#include "MoveSplineInit.h"
+#include "TargetedMovementGenerator.h"
+#include "Unit.h"
+#include "WaypointDefines.h"
+#include "WaypointMovementGenerator.h"
inline MovementGenerator* GetIdleMovementGenerator()
{
@@ -70,7 +73,7 @@ void MotionMaster::Initialize()
// clear ALL movement generators (including default)
while (!empty())
{
- MovementGenerator *curr = top();
+ MovementGenerator* curr = top();
pop();
if (curr)
DirectDelete(curr);
@@ -119,21 +122,15 @@ void MotionMaster::Clear(bool reset /*= true*/)
DirectClean(reset);
}
-void MotionMaster::ClearExpireList()
+void MotionMaster::Clear(MovementSlot slot)
{
- for (auto itr : _expireList)
- DirectDelete(itr);
-
- _expireList.clear();
-
- if (empty())
- Initialize();
- else if (NeedInitTop())
- InitTop();
- else if (_cleanFlag & MMCF_RESET)
- top()->Reset(_owner);
+ if (empty() || slot >= MAX_MOTION_SLOT)
+ return;
- _cleanFlag &= ~MMCF_RESET;
+ if (_cleanFlag & MMCF_UPDATE)
+ DelayedClean(slot);
+ else
+ DirectClean(slot);
}
void MotionMaster::MovementExpired(bool reset /*= true*/)
@@ -158,27 +155,32 @@ MovementGeneratorType MotionMaster::GetCurrentMovementGeneratorType() const
return top()->GetMovementGeneratorType();
}
-MovementGeneratorType MotionMaster::GetMotionSlotType(int slot) const
+MovementGeneratorType MotionMaster::GetMotionSlotType(MovementSlot slot) const
{
- if (!_slot[slot])
+ if (empty() || slot >= MAX_MOTION_SLOT || !_slot[slot])
return MAX_MOTION_TYPE;
- else
- return _slot[slot]->GetMovementGeneratorType();
+
+ return _slot[slot]->GetMovementGeneratorType();
}
-MovementGenerator* MotionMaster::GetMotionSlot(int slot) const
+MovementGenerator* MotionMaster::GetMotionSlot(MovementSlot slot) const
{
- ASSERT(slot >= 0);
+ if (empty() || slot >= MAX_MOTION_SLOT || !_slot[slot])
+ return nullptr;
+
return _slot[slot];
}
void MotionMaster::PropagateSpeedChange()
{
- for (int i = 0; i <= _top; ++i)
- {
- if (_slot[i])
- _slot[i]->UnitSpeedChanged();
- }
+ if (empty())
+ return;
+
+ MovementGenerator* movement = top();
+ if (!movement)
+ return;
+
+ movement->UnitSpeedChanged();
}
bool MotionMaster::GetDestination(float &x, float &y, float &z)
@@ -675,16 +677,21 @@ void MotionMaster::MoveDistract(uint32 timer)
Mutate(mgen, MOTION_SLOT_CONTROLLED);
}
-void MotionMaster::MovePath(uint32 path_id, bool repeatable)
+void MotionMaster::MovePath(uint32 pathId, bool repeatable)
{
- if (!path_id)
+ if (!pathId)
return;
- Mutate(new WaypointMovementGenerator<Creature>(path_id, repeatable), MOTION_SLOT_IDLE);
+ Mutate(new WaypointMovementGenerator<Creature>(pathId, repeatable), MOTION_SLOT_IDLE);
+
+ TC_LOG_DEBUG("misc", "%s (GUID: %u) starts moving over path(Id:%u, repeatable: %s).", _owner->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature", _owner->GetGUID().GetCounter(), pathId, repeatable ? "YES" : "NO");
+}
+
+void MotionMaster::MovePath(WaypointPath& path, bool repeatable)
+{
+ Mutate(new WaypointMovementGenerator<Creature>(path, repeatable), MOTION_SLOT_IDLE);
- TC_LOG_DEBUG("misc", "%s (GUID: %u) starts moving over path(Id:%u, repeatable: %s).",
- _owner->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature",
- _owner->GetGUID().GetCounter(), path_id, repeatable ? "YES" : "NO");
+ TC_LOG_DEBUG("misc", "%s (GUID: %u) start moving over path(repeatable: %s)", _owner->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature", _owner->GetGUID().GetCounter(), repeatable ? "YES" : "NO");
}
void MotionMaster::MoveRotate(uint32 time, RotateDirection direction)
@@ -731,7 +738,7 @@ void MotionMaster::InitTop()
void MotionMaster::Mutate(MovementGenerator *m, MovementSlot slot)
{
- if (MovementGenerator *curr = _slot[slot])
+ if (MovementGenerator* curr = _slot[slot])
{
_slot[slot] = nullptr; // in case a new one is generated in this slot during directdelete
if (_top == slot && (_cleanFlag & MMCF_UPDATE))
@@ -758,9 +765,10 @@ void MotionMaster::DirectClean(bool reset)
{
while (size() > 1)
{
- MovementGenerator *curr = top();
+ MovementGenerator* curr = top();
pop();
- if (curr) DirectDelete(curr);
+ if (curr)
+ DirectDelete(curr);
}
if (empty())
@@ -776,18 +784,47 @@ void MotionMaster::DelayedClean()
{
while (size() > 1)
{
- MovementGenerator *curr = top();
+ MovementGenerator* curr = top();
pop();
if (curr)
DelayedDelete(curr);
}
}
+void MotionMaster::DirectClean(MovementSlot slot)
+{
+ if (MovementGenerator* motion = GetMotionSlot(slot))
+ {
+ _slot[slot] = nullptr;
+ DirectDelete(motion);
+ }
+
+ while (!empty() && !top())
+ --_top;
+
+ if (empty())
+ Initialize();
+ else if (NeedInitTop())
+ InitTop();
+}
+
+void MotionMaster::DelayedClean(MovementSlot slot)
+{
+ if (MovementGenerator* motion = GetMotionSlot(slot))
+ {
+ _slot[slot] = nullptr;
+ DelayedDelete(motion);
+ }
+
+ while (!empty() && !top())
+ --_top;
+}
+
void MotionMaster::DirectExpire(bool reset)
{
if (size() > 1)
{
- MovementGenerator *curr = top();
+ MovementGenerator* curr = top();
pop();
DirectDelete(curr);
}
@@ -807,7 +844,7 @@ void MotionMaster::DelayedExpire()
{
if (size() > 1)
{
- MovementGenerator *curr = top();
+ MovementGenerator* curr = top();
pop();
DelayedDelete(curr);
}
@@ -826,9 +863,26 @@ void MotionMaster::DirectDelete(MovementGenerator* curr)
void MotionMaster::DelayedDelete(MovementGenerator* curr)
{
- TC_LOG_FATAL("misc", "Unit (Entry %u) is trying to delete its updating Movement Generator (Type %u)!", _owner->GetEntry(), curr->GetMovementGeneratorType());
+ TC_LOG_DEBUG("misc", "MotionMaster::DelayedDelete: unit (%u) delayed deleting movement generator (type %u)", _owner->GetEntry(), curr->GetMovementGeneratorType());
if (IsStatic(curr))
return;
_expireList.push_back(curr);
}
+
+void MotionMaster::ClearExpireList()
+{
+ for (auto itr : _expireList)
+ DirectDelete(itr);
+
+ _expireList.clear();
+
+ if (empty())
+ Initialize();
+ else if (NeedInitTop())
+ InitTop();
+ else if (_cleanFlag & MMCF_RESET)
+ top()->Reset(_owner);
+
+ _cleanFlag &= ~MMCF_RESET;
+}
diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h
index 4e20f9ab814..d132d8b30d0 100644
--- a/src/server/game/Movement/MotionMaster.h
+++ b/src/server/game/Movement/MotionMaster.h
@@ -31,6 +31,7 @@ class Unit;
class PathGenerator;
struct SplineChainLink;
struct SplineChainResumeInfo;
+struct WaypointPath;
// Creature Entry ID used for waypoints show, visible only for GMs
#define VISUAL_WAYPOINT 1
@@ -61,9 +62,9 @@ enum MovementGeneratorType : uint8
MAX_MOTION_TYPE // limit
};
-enum MovementSlot
+enum MovementSlot : uint8
{
- MOTION_SLOT_IDLE,
+ MOTION_SLOT_IDLE = 0,
MOTION_SLOT_ACTIVE,
MOTION_SLOT_CONTROLLED,
MAX_MOTION_SLOT
@@ -105,11 +106,12 @@ class TC_GAME_API MotionMaster
void UpdateMotion(uint32 diff);
void Clear(bool reset = true);
+ void Clear(MovementSlot slot);
void MovementExpired(bool reset = true);
MovementGeneratorType GetCurrentMovementGeneratorType() const;
- MovementGeneratorType GetMotionSlotType(int slot) const;
- MovementGenerator* GetMotionSlot(int slot) const;
+ MovementGeneratorType GetMotionSlotType(MovementSlot slot) const;
+ MovementGenerator* GetMotionSlot(MovementSlot slot) const;
void PropagateSpeedChange();
@@ -159,7 +161,8 @@ class TC_GAME_API MotionMaster
void MoveSeekAssistanceDistract(uint32 timer);
void MoveTaxiFlight(uint32 path, uint32 pathnode);
void MoveDistract(uint32 time);
- void MovePath(uint32 path_id, bool repeatable);
+ void MovePath(uint32 pathId, bool repeatable);
+ void MovePath(WaypointPath& path, bool repeatable);
void MoveRotate(uint32 time, RotateDirection direction);
void MoveFormation(uint32 id, Position destination, uint32 moveType, bool forceRun = false, bool forceOrientation = false);
@@ -172,10 +175,12 @@ class TC_GAME_API MotionMaster
bool NeedInitTop() const;
void InitTop();
- void Mutate(MovementGenerator *m, MovementSlot slot);
+ void Mutate(MovementGenerator* m, MovementSlot slot);
void DirectClean(bool reset);
void DelayedClean();
+ void DirectClean(MovementSlot slot);
+ void DelayedClean(MovementSlot slot);
void DirectExpire(bool reset);
void DelayedExpire();
void DirectDelete(MovementGenerator* curr);
diff --git a/src/server/game/Movement/MovementGenerator.h b/src/server/game/Movement/MovementGenerator.h
index 8f75e3a2361..39b2a16cc8b 100755
--- a/src/server/game/Movement/MovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerator.h
@@ -36,10 +36,11 @@ class TC_GAME_API MovementGenerator
virtual void Finalize(Unit*) = 0;
virtual void Reset(Unit*) = 0;
virtual bool Update(Unit*, uint32 diff) = 0;
-
virtual MovementGeneratorType GetMovementGeneratorType() const = 0;
virtual void UnitSpeedChanged() { }
+ virtual void Pause(uint32/* timer = 0*/) { } // timer in ms
+ virtual void Resume(uint32/* overrideTimer = 0*/) { } // timer in ms
// used by Evade code for select point to evade with expected restart default movement
virtual bool GetResetPosition(Unit*, float& /*x*/, float& /*y*/, float& /*z*/) { return false; }
diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
index 498cdf04876..133de699e84 100644
--- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
@@ -83,11 +83,7 @@ void HomeMovementGenerator<Creature>::DoFinalize(Creature* owner)
owner->SetWalk(true);
owner->LoadCreaturesAddon();
owner->AI()->JustReachedHome();
- if (owner->isRegeneratingHealth())
- {
- owner->SetFullHealth();
- owner->SetPower(POWER_MANA, owner->GetMaxPower(POWER_MANA));
- }
+ owner->SetSpawnHealth();
}
}
diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp
index a952421833d..7da90e2d515 100755
--- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp
@@ -18,7 +18,6 @@
#include "CreatureAI.h"
#include "Creature.h"
-#include "CreatureGroups.h"
#include "Player.h"
#include "MoveSplineInit.h"
#include "MoveSpline.h"
@@ -55,8 +54,7 @@ void PointMovementGenerator<T>::DoInitialize(T* owner)
// Call for creature group update
if (Creature* creature = owner->ToCreature())
- if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature)
- creature->GetFormation()->LeaderMoveTo(Position(_x, _y, _z), _movementId);
+ creature->SignalFormationMovement(Position(_x, _y, _z), _movementId);
}
template<class T>
@@ -90,8 +88,7 @@ bool PointMovementGenerator<T>::DoUpdate(T* owner, uint32 /*diff*/)
// Call for creature group update
if (Creature* creature = owner->ToCreature())
- if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature)
- creature->GetFormation()->LeaderMoveTo(Position(_x, _y, _z), _movementId);
+ creature->SignalFormationMovement(Position(_x, _y, _z), _movementId);
}
return !owner->movespline->Finalized();
diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
index 0a1972c0972..b2a9e5b83b9 100644
--- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
@@ -18,7 +18,6 @@
#include "RandomMovementGenerator.h"
#include "Creature.h"
-#include "CreatureGroups.h"
#include "Map.h"
#include "MoveSplineInit.h"
#include "MoveSpline.h"
@@ -116,8 +115,7 @@ void RandomMovementGenerator<Creature>::SetRandomLocation(Creature* owner)
_timer.Reset(traveltime + resetTimer);
// Call for creature group update
- if (owner->GetFormation() && owner->GetFormation()->getLeader() == owner)
- owner->GetFormation()->LeaderMoveTo(position);
+ owner->SignalFormationMovement(position);
}
template<class T>
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
index f292c0a8091..74a8588163c 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
@@ -17,99 +17,135 @@
*/
#include "WaypointMovementGenerator.h"
+#include "Creature.h"
#include "CreatureAI.h"
-#include "CreatureGroups.h"
#include "Log.h"
#include "MapManager.h"
#include "MoveSpline.h"
#include "MoveSplineInit.h"
#include "ObjectMgr.h"
+#include "Player.h"
#include "Transport.h"
+#include "WaypointDefines.h"
+#include "WaypointManager.h"
#include "World.h"
+WaypointMovementGenerator<Creature>::WaypointMovementGenerator(uint32 pathId, bool repeating) : _nextMoveTime(0), _recalculateSpeed(false), _isArrivalDone(false), _pathId(pathId),
+ _repeating(repeating), _loadedFromDB(true), _stalled(false), _done(false)
+{
+}
+
+WaypointMovementGenerator<Creature>::WaypointMovementGenerator(WaypointPath& path, bool repeating) : _nextMoveTime(0), _recalculateSpeed(false), _isArrivalDone(false), _pathId(0),
+ _repeating(repeating), _loadedFromDB(false), _stalled(false), _done(false)
+{
+ _path = &path;
+}
+
void WaypointMovementGenerator<Creature>::LoadPath(Creature* creature)
{
- if (!path_id)
- path_id = creature->GetWaypointPath();
+ if (_loadedFromDB)
+ {
+ if (!_pathId)
+ _pathId = creature->GetWaypointPath();
- i_path = sWaypointMgr->GetPath(path_id);
+ _path = sWaypointMgr->GetPath(_pathId);
+ }
- if (!i_path)
+ if (!_path)
{
// No path id found for entry
- TC_LOG_ERROR("sql.sql", "WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %u DB GUID: %u) doesn't have waypoint path id: %u", creature->GetName().c_str(), creature->GetEntry(), creature->GetGUID().GetCounter(), creature->GetSpawnId(), path_id);
+ TC_LOG_ERROR("sql.sql", "WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %u DB GUID: %u) doesn't have waypoint path id: %u", creature->GetName().c_str(), creature->GetEntry(), creature->GetGUID().GetCounter(), creature->GetSpawnId(), _pathId);
return;
}
- StartMoveNow(creature);
+ _nextMoveTime.Reset(1000);
+
+ // inform AI
+ if (creature->AI())
+ creature->AI()->WaypointPathStarted(1, _path->id);
}
void WaypointMovementGenerator<Creature>::DoInitialize(Creature* creature)
{
+ _done = false;
LoadPath(creature);
- creature->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
}
void WaypointMovementGenerator<Creature>::DoFinalize(Creature* creature)
{
- creature->ClearUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
+ creature->ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
creature->SetWalk(false);
}
void WaypointMovementGenerator<Creature>::DoReset(Creature* creature)
{
- creature->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
- StartMoveNow(creature);
+ if (!_done && CanMove(creature))
+ StartMoveNow(creature);
+ else if (_done)
+ {
+ // mimic IdleMovementGenerator
+ if (!creature->IsStopped())
+ creature->StopMoving();
+ }
}
void WaypointMovementGenerator<Creature>::OnArrived(Creature* creature)
{
- if (!i_path || i_path->empty())
+ if (!_path || _path->nodes.empty())
return;
- if (m_isArrivalDone)
- return;
-
- m_isArrivalDone = true;
- if (i_path->at(i_currentNode)->event_id && urand(0, 99) < i_path->at(i_currentNode)->event_chance)
+ ASSERT(_currentNode < _path->nodes.size(), "WaypointMovementGenerator::OnArrived: tried to reference a node id (%u) which is not included in path (%u)", _currentNode, _path->id);
+ WaypointNode const &waypoint = _path->nodes.at(_currentNode);
+ if (waypoint.delay)
{
- TC_LOG_DEBUG("maps.script", "Creature movement start script %u at point %u for %s.", i_path->at(i_currentNode)->event_id, i_currentNode, creature->GetGUID().ToString().c_str());
creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
- creature->GetMap()->ScriptsStart(sWaypointScripts, i_path->at(i_currentNode)->event_id, creature, nullptr);
+ _nextMoveTime.Reset(waypoint.delay);
}
- // Inform script
- MovementInform(creature);
- creature->UpdateWaypointID(i_currentNode);
-
- if (i_path->at(i_currentNode)->delay)
+ if (waypoint.eventId && urand(0, 99) < waypoint.eventChance)
{
+ TC_LOG_DEBUG("maps.script", "Creature movement start script %u at point %u for %s.", waypoint.eventId, _currentNode, creature->GetGUID().ToString().c_str());
creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
- Stop(i_path->at(i_currentNode)->delay);
+ creature->GetMap()->ScriptsStart(sWaypointScripts, waypoint.eventId, creature, nullptr);
+ }
+
+ // inform AI
+ if (creature->AI())
+ {
+ creature->AI()->MovementInform(WAYPOINT_MOTION_TYPE, _currentNode);
+ creature->AI()->WaypointReached(waypoint.id, _path->id);
}
+
+ creature->UpdateCurrentWaypointInfo(waypoint.id, _path->id);
}
bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature)
{
- if (!i_path || i_path->empty())
- return false;
+ if (!creature || !creature->IsAlive())
+ return true;
- // Dont allow dead creatures to move
- if (!creature->IsAlive())
- return false;
+ if (_done || !_path || _path->nodes.empty())
+ return true;
- if (Stopped())
+ // if the owner is the leader of its formation, check members status
+ if (creature->IsFormationLeader() && !creature->IsFormationLeaderMoveAllowed())
+ {
+ _nextMoveTime.Reset(1000);
return true;
+ }
- bool transportPath = creature->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && creature->GetTransGUID();
+ bool transportPath = creature->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && !creature->GetTransGUID().IsEmpty();
- if (m_isArrivalDone)
+ if (_isArrivalDone)
{
- if ((i_currentNode == i_path->size() - 1) && !repeating) // If that's our last waypoint
+ ASSERT(_currentNode < _path->nodes.size(), "WaypointMovementGenerator::StartMove: tried to reference a node id (%u) which is not included in path (%u)", _currentNode, _path->id);
+ WaypointNode const &waypoint = _path->nodes.at(_currentNode);
+
+ if ((_currentNode == _path->nodes.size() - 1) && !_repeating) // If that's our last waypoint
{
- float x = i_path->at(i_currentNode)->x;
- float y = i_path->at(i_currentNode)->y;
- float z = i_path->at(i_currentNode)->z;
+ float x = waypoint.x;
+ float y = waypoint.y;
+ float z = waypoint.z;
float o = creature->GetOrientation();
if (!transportPath)
@@ -127,21 +163,31 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature)
transportPath = false;
// else if (vehicle) - this should never happen, vehicle offsets are const
}
+ _done = true;
+ creature->UpdateCurrentWaypointInfo(0, 0);
- creature->GetMotionMaster()->Initialize();
- return false;
+ // inform AI
+ if (creature->AI())
+ creature->AI()->WaypointPathEnded(waypoint.id, _path->id);
+ return true;
}
- i_currentNode = (i_currentNode+1) % i_path->size();
+ _currentNode = (_currentNode + 1) % _path->nodes.size();
+
+ // inform AI
+ if (creature->AI())
+ creature->AI()->WaypointStarted(waypoint.id, _path->id);
}
- WaypointData const* node = i_path->at(i_currentNode);
+ ASSERT(_currentNode < _path->nodes.size(), "WaypointMovementGenerator::StartMove: tried to reference a node id (%u) which is not included in path (%u)", _currentNode, _path->id);
+ WaypointNode const &waypoint = _path->nodes.at(_currentNode);
+ Position formationDest(waypoint.x, waypoint.y, waypoint.z, (waypoint.orientation && waypoint.delay) ? waypoint.orientation : 0.0f);
- m_isArrivalDone = false;
+ _isArrivalDone = false;
+ _recalculateSpeed = false;
creature->AddUnitState(UNIT_STATE_ROAMING_MOVE);
- Position formationDest(node->x, node->y, node->z, (node->orientation && node->delay) ? node->orientation : 0.0f);
Movement::MoveSplineInit init(creature);
//! If creature is on transport, we assume waypoints set in DB are already transport offsets
@@ -158,13 +204,13 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature)
//! Do not use formationDest here, MoveTo requires transport offsets due to DisableTransportPathTransformations() call
//! but formationDest contains global coordinates
- init.MoveTo(node->x, node->y, node->z);
+ init.MoveTo(waypoint.x, waypoint.y, waypoint.z);
//! Accepts angles such as 0.00001 and -0.00001, 0 must be ignored, default value in waypoint table
- if (node->orientation && node->delay)
- init.SetFacing(node->orientation);
+ if (waypoint.orientation && waypoint.delay)
+ init.SetFacing(waypoint.orientation);
- switch (node->move_type)
+ switch (waypoint.moveType)
{
case WAYPOINT_MOVE_TYPE_LAND:
init.SetAnimation(Movement::ToGround);
@@ -178,87 +224,135 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature)
case WAYPOINT_MOVE_TYPE_WALK:
init.SetWalk(true);
break;
+ default:
+ break;
}
init.Launch();
- // Call for creature group update
- if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature)
- creature->GetFormation()->LeaderMoveTo(formationDest, node->id, node->move_type, (node->orientation && node->delay) ? true : false);
+ // inform formation
+ creature->SignalFormationMovement(formationDest, waypoint.id, waypoint.moveType, (waypoint.orientation && waypoint.delay) ? true : false);
return true;
}
bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* creature, uint32 diff)
{
- // Waypoint movement can be switched on/off
- // This is quite handy for escort quests and other stuff
- if (creature->HasUnitState(UNIT_STATE_NOT_MOVE))
+ if (!creature || !creature->IsAlive())
+ return true;
+
+ if (_done || !_path || _path->nodes.empty())
+ return true;
+
+ if (_stalled || creature->HasUnitState(UNIT_STATE_NOT_MOVE) || creature->IsMovementPreventedByCasting())
{
- creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
+ creature->StopMoving();
return true;
}
- // prevent a crash at empty waypoint path.
- if (!i_path || i_path->empty())
- return false;
- if (Stopped())
+ if (!_nextMoveTime.Passed())
{
- if (CanMove(diff))
- return StartMove(creature);
+ if (creature->movespline->Finalized())
+ {
+ _nextMoveTime.Update(diff);
+ if (_nextMoveTime.Passed())
+ return StartMoveNow(creature);
+ }
}
else
{
- // Set home position at place on waypoint movement.
- if (!creature->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) || !creature->GetTransGUID())
- creature->SetHomePosition(creature->GetPosition());
-
- if (creature->IsStopped())
- Stop(sWorld->getIntConfig(CONFIG_CREATURE_STOP_FOR_PLAYER));
- else if (creature->movespline->Finalized())
+ if (creature->movespline->Finalized())
{
OnArrived(creature);
- return StartMove(creature);
+ _isArrivalDone = true;
+
+ if (_nextMoveTime.Passed())
+ return StartMove(creature);
+ }
+ else
+ {
+ // Set home position at place on waypoint movement.
+ if (!creature->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) || creature->GetTransGUID().IsEmpty())
+ creature->SetHomePosition(creature->GetPosition());
+
+ if (_recalculateSpeed)
+ {
+ if (_nextMoveTime.Passed())
+ StartMove(creature);
+ }
}
}
- return true;
- }
+ return true;
+}
void WaypointMovementGenerator<Creature>::MovementInform(Creature* creature)
{
if (creature->AI())
- creature->AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode);
+ creature->AI()->MovementInform(WAYPOINT_MOTION_TYPE, _currentNode);
}
bool WaypointMovementGenerator<Creature>::GetResetPos(Creature*, float& x, float& y, float& z)
{
// prevent a crash at empty waypoint path.
- if (!i_path || i_path->empty())
+ if (!_path || _path->nodes.empty())
return false;
- WaypointData const* node = i_path->at(i_currentNode);
- x = node->x; y = node->y; z = node->z;
+ ASSERT(_currentNode < _path->nodes.size(), "WaypointMovementGenerator::GetResetPos: tried to reference a node id (%u) which is not included in path (%u)", _currentNode, _path->id);
+ WaypointNode const &waypoint = _path->nodes.at(_currentNode);
+
+ x = waypoint.x;
+ y = waypoint.y;
+ z = waypoint.z;
return true;
}
+void WaypointMovementGenerator<Creature>::Pause(uint32 timer/* = 0*/)
+{
+ _stalled = timer ? false : true;
+ _nextMoveTime.Reset(timer ? timer : 1);
+}
+
+void WaypointMovementGenerator<Creature>::Resume(uint32 overrideTimer/* = 0*/)
+{
+ _stalled = false;
+ if (overrideTimer)
+ _nextMoveTime.Reset(overrideTimer);
+}
+
+bool WaypointMovementGenerator<Creature>::CanMove(Creature* creature)
+{
+ return _nextMoveTime.Passed() && !creature->HasUnitState(UNIT_STATE_NOT_MOVE) && !creature->IsMovementPreventedByCasting();
+}
//----------------------------------------------------//
+#define FLIGHT_TRAVEL_UPDATE 100
+#define TIMEDIFF_NEXT_WP 250
+#define SKIP_SPLINE_POINT_DISTANCE_SQ (40.f * 40.f)
+#define PLAYER_FLIGHT_SPEED 32.0f
+
+FlightPathMovementGenerator::FlightPathMovementGenerator(uint32 startNode)
+{
+ _currentNode = startNode;
+ _endGridX = 0.0f;
+ _endGridY = 0.0f;
+ _endMapId = 0;
+ _preloadTargetNode = 0;
+}
+
uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const
{
- if (i_currentNode >= i_path.size())
- return i_path.size();
+ if (_currentNode >= _path.size())
+ return _path.size();
- uint32 curMapId = i_path[i_currentNode]->MapID;
- for (uint32 i = i_currentNode; i < i_path.size(); ++i)
- if (i_path[i]->MapID != curMapId)
- return i;
+ uint32 curMapId = _path[_currentNode]->MapID;
+ for (uint32 itr = _currentNode; itr < _path.size(); ++itr)
+ if (_path[itr]->MapID != curMapId)
+ return itr;
- return i_path.size();
+ return _path.size();
}
-#define SKIP_SPLINE_POINT_DISTANCE_SQ (40.0f * 40.0f)
-
bool IsNodeIncludedInShortenedPath(TaxiPathNodeEntry const* p1, TaxiPathNodeEntry const* p2)
{
return p1->MapID != p2->MapID || std::pow(p1->LocX - p2->LocX, 2) + std::pow(p1->LocY - p2->LocY, 2) > SKIP_SPLINE_POINT_DISTANCE_SQ;
@@ -268,6 +362,7 @@ void FlightPathMovementGenerator::LoadPath(Player* player)
{
_pointsForPathSwitch.clear();
std::deque<uint32> const& taxi = player->m_taxi.GetPath();
+ float discount = player->GetReputationPriceDiscount(player->m_taxi.GetFlightMasterFactionTemplate());
for (uint32 src = 0, dst = 1; dst < taxi.size(); src = dst++)
{
uint32 path, cost;
@@ -283,24 +378,24 @@ void FlightPathMovementGenerator::LoadPath(Player* player)
bool passedPreviousSegmentProximityCheck = false;
for (uint32 i = 0; i < nodes.size(); ++i)
{
- if (passedPreviousSegmentProximityCheck || !src || i_path.empty() || IsNodeIncludedInShortenedPath(i_path[i_path.size() - 1], nodes[i]))
+ if (passedPreviousSegmentProximityCheck || !src || _path.empty() || IsNodeIncludedInShortenedPath(_path[_path.size() - 1], nodes[i]))
{
if ((!src || (IsNodeIncludedInShortenedPath(start, nodes[i]) && i >= 2)) &&
(dst == taxi.size() - 1 || (IsNodeIncludedInShortenedPath(end, nodes[i]) && i < nodes.size() - 1)))
{
passedPreviousSegmentProximityCheck = true;
- i_path.push_back(nodes[i]);
+ _path.push_back(nodes[i]);
}
}
else
{
- i_path.pop_back();
+ _path.pop_back();
--_pointsForPathSwitch.back().PathIndex;
}
}
}
- _pointsForPathSwitch.push_back({ uint32(i_path.size() - 1), int32(cost) });
+ _pointsForPathSwitch.push_back({ uint32(_path.size() - 1), int32(ceil(cost * discount)) });
}
}
@@ -331,8 +426,6 @@ void FlightPathMovementGenerator::DoFinalize(Player* player)
player->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_TAXI_BENCHMARK);
}
-#define PLAYER_FLIGHT_SPEED 32.0f
-
void FlightPathMovementGenerator::DoReset(Player* player)
{
player->getHostileRefManager().setOnlineOfflineState(false);
@@ -343,7 +436,7 @@ void FlightPathMovementGenerator::DoReset(Player* player)
uint32 end = GetPathAtMapEnd();
for (uint32 i = GetCurrentNode(); i != end; ++i)
{
- G3D::Vector3 vertice(i_path[i]->LocX, i_path[i]->LocY, i_path[i]->LocZ);
+ G3D::Vector3 vertice(_path[i]->LocX, _path[i]->LocY, _path[i]->LocZ);
init.Path().push_back(vertice);
}
init.SetFirstPointId(GetCurrentNode());
@@ -355,13 +448,13 @@ void FlightPathMovementGenerator::DoReset(Player* player)
bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/)
{
uint32 pointId = (uint32)player->movespline->currentPathIdx();
- if (pointId > i_currentNode)
+ if (pointId > _currentNode)
{
bool departureEvent = true;
do
{
- DoEventIfAny(player, i_path[i_currentNode], departureEvent);
- while (!_pointsForPathSwitch.empty() && _pointsForPathSwitch.front().PathIndex <= i_currentNode)
+ DoEventIfAny(player, _path[_currentNode], departureEvent);
+ while (!_pointsForPathSwitch.empty() && _pointsForPathSwitch.front().PathIndex <= _currentNode)
{
_pointsForPathSwitch.pop_front();
player->m_taxi.NextTaxiDestination();
@@ -372,31 +465,31 @@ bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/)
}
}
- if (pointId == i_currentNode)
+ if (pointId == _currentNode)
break;
- if (i_currentNode == _preloadTargetNode)
+ if (_currentNode == _preloadTargetNode)
PreloadEndGrid();
- i_currentNode += (uint32)departureEvent;
+ _currentNode += departureEvent ? 1 : 0;
departureEvent = !departureEvent;
}
while (true);
}
- return i_currentNode < (i_path.size() - 1);
+ return _currentNode < (_path.size() - 1);
}
void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport()
{
- if (i_path.empty() || i_currentNode >= i_path.size())
+ if (_path.empty() || _currentNode >= _path.size())
return;
- uint32 map0 = i_path[i_currentNode]->MapID;
- for (size_t i = i_currentNode + 1; i < i_path.size(); ++i)
+ uint32 map0 = _path[_currentNode]->MapID;
+ for (size_t i = _currentNode + 1; i < _path.size(); ++i)
{
- if (i_path[i]->MapID != map0)
+ if (_path[i]->MapID != map0)
{
- i_currentNode = i;
+ _currentNode = i;
return;
}
}
@@ -413,7 +506,7 @@ void FlightPathMovementGenerator::DoEventIfAny(Player* player, TaxiPathNodeEntry
bool FlightPathMovementGenerator::GetResetPos(Player*, float& x, float& y, float& z)
{
- TaxiPathNodeEntry const* node = i_path[i_currentNode];
+ TaxiPathNodeEntry const* node = _path[_currentNode];
x = node->LocX;
y = node->LocY;
z = node->LocZ;
@@ -424,11 +517,11 @@ void FlightPathMovementGenerator::InitEndGridInfo()
{
/*! Storage to preload flightmaster grid at end of flight. For multi-stop flights, this will
be reinitialized for each flightmaster at the end of each spline (or stop) in the flight. */
- uint32 nodeCount = i_path.size(); //! Number of nodes in path.
- _endMapId = i_path[nodeCount - 1]->MapID; //! MapId of last node
+ uint32 nodeCount = _path.size(); //! Number of nodes in path.
+ _endMapId = _path[nodeCount - 1]->MapID; //! MapId of last node
_preloadTargetNode = nodeCount - 3;
- _endGridX = i_path[nodeCount - 1]->LocX;
- _endGridY = i_path[nodeCount - 1]->LocY;
+ _endGridX = _path[nodeCount - 1]->LocX;
+ _endGridY = _path[nodeCount - 1]->LocY;
}
void FlightPathMovementGenerator::PreloadEndGrid()
@@ -439,7 +532,7 @@ void FlightPathMovementGenerator::PreloadEndGrid()
// Load the grid
if (endMap)
{
- TC_LOG_DEBUG("misc", "Preloading rid (%f, %f) for map %u at node index %u/%u", _endGridX, _endGridY, _endMapId, _preloadTargetNode, (uint32)(i_path.size() - 1));
+ TC_LOG_DEBUG("misc", "Preloading rid (%f, %f) for map %u at node index %u/%u", _endGridX, _endGridY, _endMapId, _preloadTargetNode, (uint32)(_path.size() - 1));
endMap->LoadGrid(_endGridX, _endGridY);
}
else
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
index 7426a166ea1..e447bad7bb8 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
@@ -19,103 +19,91 @@
#ifndef TRINITY_WAYPOINTMOVEMENTGENERATOR_H
#define TRINITY_WAYPOINTMOVEMENTGENERATOR_H
-/** @page PathMovementGenerator is used to generate movements
+/**
+ * @page PathMovementGenerator is used to generate movements
* of waypoints and flight paths. Each serves the purpose
* of generate activities so that it generates updated
* packets for the players.
*/
-#include "MovementGenerator.h"
-#include "Creature.h"
#include "DBCStructure.h"
-#include "Player.h"
+#include "MovementGenerator.h"
#include "Timer.h"
-#include "WaypointManager.h"
-#define FLIGHT_TRAVEL_UPDATE 100
-#define TIMEDIFF_NEXT_WP 250
+class Creature;
+class Player;
+struct WaypointPath;
-template<class T, class P>
+template<class Entity, class BasePath>
class PathMovementBase
{
public:
- PathMovementBase() : i_path(), i_currentNode(0) { }
+ PathMovementBase() : _path(), _currentNode(0) { }
virtual ~PathMovementBase() { };
- uint32 GetCurrentNode() const { return i_currentNode; }
+ uint32 GetCurrentNode() const { return _currentNode; }
protected:
- P i_path;
- uint32 i_currentNode;
+ BasePath _path;
+ uint32 _currentNode;
};
template<class T>
class WaypointMovementGenerator;
template<>
-class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium< Creature, WaypointMovementGenerator<Creature> >,
- public PathMovementBase<Creature, WaypointPath const*>
+class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium<Creature, WaypointMovementGenerator<Creature>>, public PathMovementBase<Creature, WaypointPath const*>
{
public:
- WaypointMovementGenerator(uint32 _path_id = 0, bool _repeating = true)
- : i_nextMoveTime(0), m_isArrivalDone(false), path_id(_path_id), repeating(_repeating) { }
- ~WaypointMovementGenerator() { i_path = nullptr; }
+ explicit WaypointMovementGenerator(uint32 pathId = 0, bool repeating = true);
+ explicit WaypointMovementGenerator(WaypointPath& path, bool repeating = true);
+
+ ~WaypointMovementGenerator() { _path = nullptr; }
+
void DoInitialize(Creature*);
void DoFinalize(Creature*);
void DoReset(Creature*);
bool DoUpdate(Creature*, uint32 diff);
- void MovementInform(Creature*);
-
MovementGeneratorType GetMovementGeneratorType() const override { return WAYPOINT_MOTION_TYPE; }
+ void UnitSpeedChanged() override { _recalculateSpeed = true; }
+ void Pause(uint32 timer = 0) override;
+ void Resume(uint32 overrideTimer = 0) override;
- // now path movement implmementation
- void LoadPath(Creature*);
+ void MovementInform(Creature*);
bool GetResetPos(Creature*, float& x, float& y, float& z);
private:
-
- void Stop(int32 time) { i_nextMoveTime.Reset(time);}
-
- bool Stopped() { return !i_nextMoveTime.Passed();}
-
- bool CanMove(int32 diff)
- {
- i_nextMoveTime.Update(diff);
- return i_nextMoveTime.Passed();
- }
-
+ void LoadPath(Creature*);
void OnArrived(Creature*);
bool StartMove(Creature*);
-
- void StartMoveNow(Creature* creature)
+ bool CanMove(Creature*);
+ bool StartMoveNow(Creature* creature)
{
- i_nextMoveTime.Reset(0);
- StartMove(creature);
+ _nextMoveTime.Reset(0);
+ return StartMove(creature);
}
- TimeTrackerSmall i_nextMoveTime;
- bool m_isArrivalDone;
- uint32 path_id;
- bool repeating;
+ TimeTrackerSmall _nextMoveTime;
+ bool _recalculateSpeed;
+ bool _isArrivalDone;
+ uint32 _pathId;
+ bool _repeating;
+ bool _loadedFromDB;
+ bool _stalled;
+ bool _done;
};
-/** FlightPathMovementGenerator generates movement of the player for the paths
+/**
+ * FlightPathMovementGenerator generates movement of the player for the paths
* and hence generates ground and activities for the player.
*/
-class FlightPathMovementGenerator : public MovementGeneratorMedium< Player, FlightPathMovementGenerator >,
- public PathMovementBase<Player, TaxiPathNodeList>
+class FlightPathMovementGenerator : public MovementGeneratorMedium<Player, FlightPathMovementGenerator>, public PathMovementBase<Player, TaxiPathNodeList>
{
public:
- explicit FlightPathMovementGenerator(uint32 startNode = 0)
- {
- i_currentNode = startNode;
- _endGridX = 0.0f;
- _endGridY = 0.0f;
- _endMapId = 0;
- _preloadTargetNode = 0;
- }
+ explicit FlightPathMovementGenerator(uint32 startNode = 0);
+
void LoadPath(Player* player);
void DoInitialize(Player*);
void DoReset(Player*);
@@ -123,15 +111,14 @@ class FlightPathMovementGenerator : public MovementGeneratorMedium< Player, Flig
bool DoUpdate(Player*, uint32);
MovementGeneratorType GetMovementGeneratorType() const override { return FLIGHT_MOTION_TYPE; }
- TaxiPathNodeList const& GetPath() { return i_path; }
+ TaxiPathNodeList const& GetPath() { return _path; }
uint32 GetPathAtMapEnd() const;
- bool HasArrived() const { return (i_currentNode >= i_path.size()); }
+ bool HasArrived() const { return (_currentNode >= _path.size()); }
void SetCurrentNodeAfterTeleport();
- void SkipCurrentNode() { ++i_currentNode; }
+ void SkipCurrentNode() { ++_currentNode; }
void DoEventIfAny(Player* player, TaxiPathNodeEntry const* node, bool departure);
bool GetResetPos(Player*, float& x, float& y, float& z);
-
void InitEndGridInfo();
void PreloadEndGrid();
diff --git a/src/server/game/Movement/Waypoints/WaypointDefines.h b/src/server/game/Movement/Waypoints/WaypointDefines.h
new file mode 100644
index 00000000000..dbb7a15fa5c
--- /dev/null
+++ b/src/server/game/Movement/Waypoints/WaypointDefines.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TRINITY_WAYPOINTDEFINES_H
+#define TRINITY_WAYPOINTDEFINES_H
+
+#include "Define.h"
+#include <vector>
+
+enum WaypointMoveType
+{
+ WAYPOINT_MOVE_TYPE_WALK,
+ WAYPOINT_MOVE_TYPE_RUN,
+ WAYPOINT_MOVE_TYPE_LAND,
+ WAYPOINT_MOVE_TYPE_TAKEOFF,
+
+ WAYPOINT_MOVE_TYPE_MAX
+};
+
+struct WaypointNode
+{
+ WaypointNode() : id(0), x(0.f), y(0.f), z(0.f), orientation(0.f), delay(0), eventId(0), moveType(WAYPOINT_MOVE_TYPE_RUN), eventChance(0) { }
+ WaypointNode(uint32 _id, float _x, float _y, float _z, float _orientation = 0.f, uint32 _delay = 0)
+ {
+ id = _id;
+ x = _x;
+ y = _y;
+ z = _z;
+ orientation = _orientation;
+ delay = _delay;
+ eventId = 0;
+ moveType = WAYPOINT_MOVE_TYPE_WALK;
+ eventChance = 100;
+ }
+
+ uint32 id;
+ float x, y, z, orientation;
+ uint32 delay;
+ uint32 eventId;
+ uint32 moveType;
+ uint8 eventChance;
+};
+
+struct WaypointPath
+{
+ WaypointPath() : id(0) { }
+ WaypointPath(uint32 _id, std::vector<WaypointNode>&& _nodes)
+ {
+ id = _id;
+ nodes = _nodes;
+ }
+
+ std::vector<WaypointNode> nodes;
+ uint32 id;
+};
+
+#endif
diff --git a/src/server/game/Movement/Waypoints/WaypointManager.cpp b/src/server/game/Movement/Waypoints/WaypointManager.cpp
index 76c6228d302..71b2c29621b 100644
--- a/src/server/game/Movement/Waypoints/WaypointManager.cpp
+++ b/src/server/game/Movement/Waypoints/WaypointManager.cpp
@@ -16,27 +16,12 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "WaypointManager.h"
#include "DatabaseEnv.h"
#include "GridDefines.h"
-#include "WaypointManager.h"
#include "MapManager.h"
#include "Log.h"
-WaypointMgr::WaypointMgr() { }
-
-WaypointMgr::~WaypointMgr()
-{
- for (WaypointPathContainer::iterator itr = _waypointStore.begin(); itr != _waypointStore.end(); ++itr)
- {
- for (WaypointPath::const_iterator it = itr->second.begin(); it != itr->second.end(); ++it)
- delete *it;
-
- itr->second.clear();
- }
-
- _waypointStore.clear();
-}
-
void WaypointMgr::Load()
{
uint32 oldMSTime = getMSTime();
@@ -46,7 +31,7 @@ void WaypointMgr::Load()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 waypoints. DB table `waypoint_data` is empty!");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 waypoints. DB table `waypoint_data` is empty!");
return;
}
@@ -55,11 +40,7 @@ void WaypointMgr::Load()
do
{
Field* fields = result->Fetch();
- WaypointData* wp = new WaypointData();
-
uint32 pathId = fields[0].GetUInt32();
- WaypointPath& path = _waypointStore[pathId];
-
float x = fields[2].GetFloat();
float y = fields[3].GetFloat();
float z = fields[4].GetFloat();
@@ -68,25 +49,27 @@ void WaypointMgr::Load()
Trinity::NormalizeMapCoord(x);
Trinity::NormalizeMapCoord(y);
- wp->id = fields[1].GetUInt32();
- wp->x = x;
- wp->y = y;
- wp->z = z;
- wp->orientation = o;
- wp->move_type = fields[6].GetUInt32();
+ WaypointNode waypoint;
+ waypoint.id = fields[1].GetUInt32();
+ waypoint.x = x;
+ waypoint.y = y;
+ waypoint.z = z;
+ waypoint.orientation = o;
+ waypoint.moveType = fields[6].GetUInt32();
- if (wp->move_type >= WAYPOINT_MOVE_TYPE_MAX)
+ if (waypoint.moveType >= WAYPOINT_MOVE_TYPE_MAX)
{
- TC_LOG_ERROR("sql.sql", "Waypoint %u in waypoint_data has invalid move_type, ignoring", wp->id);
- delete wp;
+ TC_LOG_ERROR("sql.sql", "Waypoint %u in waypoint_data has invalid move_type, ignoring", waypoint.id);
continue;
}
- wp->delay = fields[7].GetUInt32();
- wp->event_id = fields[8].GetUInt32();
- wp->event_chance = fields[9].GetInt16();
+ waypoint.delay = fields[7].GetUInt32();
+ waypoint.eventId = fields[8].GetUInt32();
+ waypoint.eventChance = fields[9].GetInt16();
- path.push_back(wp);
+ WaypointPath& path = _waypointStore[pathId];
+ path.id = pathId;
+ path.nodes.push_back(std::move(waypoint));
++count;
}
while (result->NextRow());
@@ -102,14 +85,9 @@ WaypointMgr* WaypointMgr::instance()
void WaypointMgr::ReloadPath(uint32 id)
{
- WaypointPathContainer::iterator itr = _waypointStore.find(id);
+ auto itr = _waypointStore.find(id);
if (itr != _waypointStore.end())
- {
- for (WaypointPath::const_iterator it = itr->second.begin(); it != itr->second.end(); ++it)
- delete *it;
-
_waypointStore.erase(itr);
- }
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_BY_ID);
@@ -120,13 +98,10 @@ void WaypointMgr::ReloadPath(uint32 id)
if (!result)
return;
- WaypointPath& path = _waypointStore[id];
-
+ std::vector<WaypointNode> values;
do
{
Field* fields = result->Fetch();
- WaypointData* wp = new WaypointData();
-
float x = fields[1].GetFloat();
float y = fields[2].GetFloat();
float z = fields[3].GetFloat();
@@ -135,26 +110,36 @@ void WaypointMgr::ReloadPath(uint32 id)
Trinity::NormalizeMapCoord(x);
Trinity::NormalizeMapCoord(y);
- wp->id = fields[0].GetUInt32();
- wp->x = x;
- wp->y = y;
- wp->z = z;
- wp->orientation = o;
- wp->move_type = fields[5].GetUInt32();
+ WaypointNode waypoint;
+ waypoint.id = fields[0].GetUInt32();
+ waypoint.x = x;
+ waypoint.y = y;
+ waypoint.z = z;
+ waypoint.orientation = o;
+ waypoint.moveType = fields[5].GetUInt32();
- if (wp->move_type >= WAYPOINT_MOVE_TYPE_MAX)
+ if (waypoint.moveType >= WAYPOINT_MOVE_TYPE_MAX)
{
- TC_LOG_ERROR("sql.sql", "Waypoint %u in waypoint_data has invalid move_type, ignoring", wp->id);
- delete wp;
+ TC_LOG_ERROR("sql.sql", "Waypoint %u in waypoint_data has invalid move_type, ignoring", waypoint.id);
continue;
}
- wp->delay = fields[6].GetUInt32();
- wp->event_id = fields[7].GetUInt32();
- wp->event_chance = fields[8].GetUInt8();
-
- path.push_back(wp);
+ waypoint.delay = fields[6].GetUInt32();
+ waypoint.eventId = fields[7].GetUInt32();
+ waypoint.eventChance = fields[8].GetUInt8();
+ values.push_back(std::move(waypoint));
}
while (result->NextRow());
+
+ _waypointStore[id] = WaypointPath(id, std::move(values));
+}
+
+WaypointPath const* WaypointMgr::GetPath(uint32 id) const
+{
+ auto itr = _waypointStore.find(id);
+ if (itr != _waypointStore.end())
+ return &itr->second;
+
+ return nullptr;
}
diff --git a/src/server/game/Movement/Waypoints/WaypointManager.h b/src/server/game/Movement/Waypoints/WaypointManager.h
index f62805594ef..769e45432e7 100644
--- a/src/server/game/Movement/Waypoints/WaypointManager.h
+++ b/src/server/game/Movement/Waypoints/WaypointManager.h
@@ -20,32 +20,10 @@
#define TRINITY_WAYPOINTMANAGER_H
#include "Define.h"
+#include "WaypointDefines.h"
#include <vector>
#include <unordered_map>
-enum WaypointMoveType
-{
- WAYPOINT_MOVE_TYPE_WALK,
- WAYPOINT_MOVE_TYPE_RUN,
- WAYPOINT_MOVE_TYPE_LAND,
- WAYPOINT_MOVE_TYPE_TAKEOFF,
-
- WAYPOINT_MOVE_TYPE_MAX
-};
-
-struct WaypointData
-{
- uint32 id;
- float x, y, z, orientation;
- uint32 delay;
- uint32 event_id;
- uint32 move_type;
- uint8 event_chance;
-};
-
-typedef std::vector<WaypointData*> WaypointPath;
-typedef std::unordered_map<uint32, WaypointPath> WaypointPathContainer;
-
class TC_GAME_API WaypointMgr
{
public:
@@ -58,20 +36,12 @@ class TC_GAME_API WaypointMgr
void Load();
// Returns the path from a given id
- WaypointPath const* GetPath(uint32 id) const
- {
- WaypointPathContainer::const_iterator itr = _waypointStore.find(id);
- if (itr != _waypointStore.end())
- return &itr->second;
-
- return nullptr;
- }
+ WaypointPath const* GetPath(uint32 id) const;
private:
- WaypointMgr();
- ~WaypointMgr();
+ WaypointMgr() { }
- WaypointPathContainer _waypointStore;
+ std::unordered_map<uint32, WaypointPath> _waypointStore;
};
#define sWaypointMgr WaypointMgr::instance()
diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.cpp b/src/server/game/OutdoorPvP/OutdoorPvP.cpp
index a2d195bea20..b2e962abc0f 100644
--- a/src/server/game/OutdoorPvP/OutdoorPvP.cpp
+++ b/src/server/game/OutdoorPvP/OutdoorPvP.cpp
@@ -91,7 +91,7 @@ void OPvPCapturePoint::AddGO(uint32 type, ObjectGuid::LowType guid, uint32 entry
{
if (!entry)
{
- GameObjectData const* data = sObjectMgr->GetGOData(guid);
+ GameObjectData const* data = sObjectMgr->GetGameObjectData(guid);
if (!data)
return;
entry = data->id;
@@ -117,7 +117,7 @@ void OPvPCapturePoint::AddCre(uint32 type, ObjectGuid::LowType guid, uint32 entr
bool OPvPCapturePoint::AddObject(uint32 type, uint32 entry, uint32 map, Position const& pos, QuaternionData const& rot)
{
- if (ObjectGuid::LowType guid = sObjectMgr->AddGOData(entry, map, pos, rot, 0))
+ if (ObjectGuid::LowType guid = sObjectMgr->AddGameObjectData(entry, map, pos, rot, 0))
{
AddGO(type, guid, entry);
return true;
@@ -149,7 +149,7 @@ bool OPvPCapturePoint::SetCapturePointData(uint32 entry, uint32 map, Position co
return false;
}
- m_capturePointSpawnId = sObjectMgr->AddGOData(entry, map, pos, rot, 0);
+ m_capturePointSpawnId = sObjectMgr->AddGameObjectData(entry, map, pos, rot, 0);
if (m_capturePointSpawnId == 0)
return false;
@@ -217,7 +217,7 @@ bool OPvPCapturePoint::DelObject(uint32 type)
go->SetRespawnTime(0);
go->Delete();
}
- sObjectMgr->DeleteGOData(spawnId);
+ sObjectMgr->DeleteGameObjectData(spawnId);
m_ObjectTypes[m_Objects[type]] = 0;
m_Objects[type] = 0;
return true;
@@ -225,7 +225,7 @@ bool OPvPCapturePoint::DelObject(uint32 type)
bool OPvPCapturePoint::DelCapturePoint()
{
- sObjectMgr->DeleteGOData(m_capturePointSpawnId);
+ sObjectMgr->DeleteGameObjectData(m_capturePointSpawnId);
m_capturePointSpawnId = 0;
if (m_capturePoint)
diff --git a/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp b/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp
index ebe3d568beb..48456efb424 100644
--- a/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp
+++ b/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp
@@ -54,7 +54,7 @@ void OutdoorPvPMgr::InitOutdoorPvP()
QueryResult result = WorldDatabase.Query("SELECT TypeId, ScriptName FROM outdoorpvp_template");
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 outdoor PvP definitions. DB table `outdoorpvp_template` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 outdoor PvP definitions. DB table `outdoorpvp_template` is empty.");
return;
}
diff --git a/src/server/game/Pools/PoolMgr.cpp b/src/server/game/Pools/PoolMgr.cpp
index 9305e226421..25b9bd5f363 100644
--- a/src/server/game/Pools/PoolMgr.cpp
+++ b/src/server/game/Pools/PoolMgr.cpp
@@ -153,34 +153,6 @@ bool PoolGroup<T>::CheckPool() const
return true;
}
-template <class T>
-PoolObject* PoolGroup<T>::RollOne(ActivePoolData& spawns, uint32 triggerFrom)
-{
- if (!ExplicitlyChanced.empty())
- {
- float roll = (float)rand_chance();
-
- for (uint32 i = 0; i < ExplicitlyChanced.size(); ++i)
- {
- roll -= ExplicitlyChanced[i].chance;
- // Triggering object is marked as spawned at this time and can be also rolled (respawn case)
- // so this need explicit check for this case
- if (roll < 0 && (ExplicitlyChanced[i].guid == triggerFrom || !spawns.IsActiveObject<T>(ExplicitlyChanced[i].guid)))
- return &ExplicitlyChanced[i];
- }
- }
- if (!EqualChanced.empty())
- {
- uint32 index = urand(0, EqualChanced.size()-1);
- // Triggering object is marked as spawned at this time and can be also rolled (respawn case)
- // so this need explicit check for this case
- if (EqualChanced[index].guid == triggerFrom || !spawns.IsActiveObject<T>(EqualChanced[index].guid))
- return &EqualChanced[index];
- }
-
- return nullptr;
-}
-
// Main method to despawn a creature or gameobject in a pool
// If no guid is passed, the pool is just removed (event end case)
// If guid is filled, cache will be used and no removal will occur, it just fill the cache
@@ -222,7 +194,7 @@ void PoolGroup<Creature>::Despawn1Object(ObjectGuid::LowType guid)
{
sObjectMgr->RemoveCreatureFromGrid(guid, data);
- Map* map = sMapMgr->CreateBaseMap(data->mapid);
+ Map* map = sMapMgr->CreateBaseMap(data->spawnPoint.GetMapId());
if (!map->Instanceable())
{
auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(guid);
@@ -230,6 +202,9 @@ void PoolGroup<Creature>::Despawn1Object(ObjectGuid::LowType guid)
{
Creature* creature = itr->second;
++itr;
+ // For dynamic spawns, save respawn time here
+ if (!creature->GetRespawnCompatibilityMode())
+ creature->SaveRespawnTime(0, false);
creature->AddObjectToRemoveList();
}
}
@@ -240,11 +215,11 @@ void PoolGroup<Creature>::Despawn1Object(ObjectGuid::LowType guid)
template<>
void PoolGroup<GameObject>::Despawn1Object(ObjectGuid::LowType guid)
{
- if (GameObjectData const* data = sObjectMgr->GetGOData(guid))
+ if (GameObjectData const* data = sObjectMgr->GetGameObjectData(guid))
{
sObjectMgr->RemoveGameobjectFromGrid(guid, data);
- Map* map = sMapMgr->CreateBaseMap(data->mapid);
+ Map* map = sMapMgr->CreateBaseMap(data->spawnPoint.GetMapId());
if (!map->Instanceable())
{
auto gameobjectBounds = map->GetGameObjectBySpawnIdStore().equal_range(guid);
@@ -252,6 +227,10 @@ void PoolGroup<GameObject>::Despawn1Object(ObjectGuid::LowType guid)
{
GameObject* go = itr->second;
++itr;
+
+ // For dynamic spawns, save respawn time here
+ if (!go->GetRespawnCompatibilityMode())
+ go->SaveRespawnTime(0, false);
go->AddObjectToRemoveList();
}
}
@@ -333,7 +312,6 @@ void PoolGroup<Pool>::RemoveOneRelation(uint32 child_pool_id)
template <class T>
void PoolGroup<T>::SpawnObject(ActivePoolData& spawns, uint32 limit, uint32 triggerFrom)
{
- uint32 lastDespawned = 0;
int count = limit - spawns.GetActiveObjectCount(poolId);
// If triggered from some object respawn this object is still marked as spawned
@@ -342,32 +320,70 @@ void PoolGroup<T>::SpawnObject(ActivePoolData& spawns, uint32 limit, uint32 trig
if (triggerFrom)
++count;
- // This will try to spawn the rest of pool, not guaranteed
- for (int i = 0; i < count; ++i)
+ if (count > 0)
{
- PoolObject* obj = RollOne(spawns, triggerFrom);
- if (!obj)
- continue;
- if (obj->guid == lastDespawned)
- continue;
+ PoolObjectList rolledObjects;
+ rolledObjects.reserve(count);
- if (obj->guid == triggerFrom)
+ // roll objects to be spawned
+ if (!ExplicitlyChanced.empty())
{
- ReSpawn1Object(obj);
- triggerFrom = 0;
- continue;
+ while (count && ExplicitlyChanced.size() > rolledObjects.size())
+ {
+ --count;
+ float roll = (float)rand_chance();
+
+ for (PoolObject& obj : ExplicitlyChanced)
+ {
+ roll -= obj.chance;
+ // Triggering object is marked as spawned at this time and can be also rolled (respawn case)
+ // so this need explicit check for this case
+ if (roll < 0 && (obj.guid == triggerFrom || !spawns.IsActiveObject<T>(obj.guid)))
+ {
+ rolledObjects.push_back(obj);
+ break;
+ }
+ }
+ }
}
- spawns.ActivateObject<T>(obj->guid, poolId);
- Spawn1Object(obj);
+ else if (!EqualChanced.empty())
+ {
+ rolledObjects = EqualChanced;
+
+ for (auto itr = rolledObjects.begin(); itr != rolledObjects.end();)
+ {
+ // remove most of the active objects so there is higher chance inactive ones are spawned
+ if (spawns.IsActiveObject<T>(itr->guid) && urand(1, 4) != 1)
+ itr = rolledObjects.erase(itr);
+ else
+ ++itr;
+ }
- if (triggerFrom)
+ Trinity::Containers::RandomResize(rolledObjects, count);
+ }
+
+ // try to spawn rolled objects
+ for (PoolObject& obj : rolledObjects)
{
- // One spawn one despawn no count increase
- DespawnObject(spawns, triggerFrom);
- lastDespawned = triggerFrom;
- triggerFrom = 0;
+ if (spawns.IsActiveObject<T>(obj.guid))
+ continue;
+
+ if (obj.guid == triggerFrom)
+ {
+ ReSpawn1Object(&obj);
+ triggerFrom = 0;
+ }
+ else
+ {
+ spawns.ActivateObject<T>(obj.guid, poolId);
+ Spawn1Object(&obj);
+ }
}
}
+
+ // One spawn one despawn no count increase
+ if (triggerFrom)
+ DespawnObject(spawns, triggerFrom);
}
// Method that is actualy doing the spawn job on 1 creature
@@ -379,13 +395,13 @@ void PoolGroup<Creature>::Spawn1Object(PoolObject* obj)
sObjectMgr->AddCreatureToGrid(obj->guid, data);
// Spawn if necessary (loaded grids only)
- Map* map = sMapMgr->CreateBaseMap(data->mapid);
+ Map* map = sMapMgr->CreateBaseMap(data->spawnPoint.GetMapId());
// We use spawn coords to spawn
- if (!map->Instanceable() && map->IsGridLoaded(data->posX, data->posY))
+ if (!map->Instanceable() && map->IsGridLoaded(data->spawnPoint))
{
Creature* creature = new Creature();
//TC_LOG_DEBUG("pool", "Spawning creature %u", guid);
- if (!creature->LoadCreatureFromDB(obj->guid, map))
+ if (!creature->LoadFromDB(obj->guid, map, true, false))
{
delete creature;
return;
@@ -398,18 +414,18 @@ void PoolGroup<Creature>::Spawn1Object(PoolObject* obj)
template <>
void PoolGroup<GameObject>::Spawn1Object(PoolObject* obj)
{
- if (GameObjectData const* data = sObjectMgr->GetGOData(obj->guid))
+ if (GameObjectData const* data = sObjectMgr->GetGameObjectData(obj->guid))
{
sObjectMgr->AddGameobjectToGrid(obj->guid, data);
// Spawn if necessary (loaded grids only)
// this base map checked as non-instanced and then only existed
- Map* map = sMapMgr->CreateBaseMap(data->mapid);
+ Map* map = sMapMgr->CreateBaseMap(data->spawnPoint.GetMapId());
// We use current coords to unspawn, not spawn coords since creature can have changed grid
- if (!map->Instanceable() && map->IsGridLoaded(data->posX, data->posY))
+ if (!map->Instanceable() && map->IsGridLoaded(data->spawnPoint))
{
GameObject* pGameobject = new GameObject;
//TC_LOG_DEBUG("pool", "Spawning gameobject %u", guid);
- if (!pGameobject->LoadGameObjectFromDB(obj->guid, map, false))
+ if (!pGameobject->LoadFromDB(obj->guid, map, false))
{
delete pGameobject;
return;
@@ -688,7 +704,7 @@ void PoolMgr::LoadFromDB()
uint32 pool_id = fields[1].GetUInt32();
float chance = fields[2].GetFloat();
- GameObjectData const* data = sObjectMgr->GetGOData(guid);
+ GameObjectData const* data = sObjectMgr->GetGameObjectData(guid);
if (!data)
{
TC_LOG_ERROR("sql.sql", "`pool_gameobject` has a non existing gameobject spawn (GUID: %u) defined for pool id (%u), skipped.", guid, pool_id);
@@ -1074,6 +1090,21 @@ void PoolMgr::DespawnPool(uint32 pool_id)
mPoolQuestGroups[pool_id].DespawnObject(mSpawnedData);
}
+// Selects proper template overload to call based on passed type
+uint32 PoolMgr::IsPartOfAPool(SpawnObjectType type, ObjectGuid::LowType spawnId) const
+{
+ switch (type)
+ {
+ case SPAWN_TYPE_CREATURE:
+ return IsPartOfAPool<Creature>(spawnId);
+ case SPAWN_TYPE_GAMEOBJECT:
+ return IsPartOfAPool<GameObject>(spawnId);
+ default:
+ ASSERT(false, "Invalid spawn type %u passed to PoolMgr::IsPartOfPool (with spawnId %u)", uint32(type), spawnId);
+ return 0;
+ }
+}
+
// Method that check chance integrity of the creatures and gameobjects in this pool
bool PoolMgr::CheckPool(uint32 pool_id) const
{
diff --git a/src/server/game/Pools/PoolMgr.h b/src/server/game/Pools/PoolMgr.h
index 6c270e28851..6de34c05fb4 100644
--- a/src/server/game/Pools/PoolMgr.h
+++ b/src/server/game/Pools/PoolMgr.h
@@ -22,6 +22,7 @@
#include "Define.h"
#include "Creature.h"
#include "GameObject.h"
+#include "SpawnData.h"
#include "QuestDef.h"
struct PoolTemplateData
@@ -76,7 +77,6 @@ class TC_GAME_API PoolGroup
bool isEmpty() const { return ExplicitlyChanced.empty() && EqualChanced.empty(); }
void AddEntry(PoolObject& poolitem, uint32 maxentries);
bool CheckPool() const;
- PoolObject* RollOne(ActivePoolData& spawns, uint32 triggerFrom);
void DespawnObject(ActivePoolData& spawns, ObjectGuid::LowType guid=0);
void Despawn1Object(ObjectGuid::LowType guid);
void SpawnObject(ActivePoolData& spawns, uint32 limit, uint32 triggerFrom);
@@ -118,6 +118,7 @@ class TC_GAME_API PoolMgr
template<typename T>
uint32 IsPartOfAPool(uint32 db_guid_or_pool_id) const;
+ uint32 IsPartOfAPool(SpawnObjectType type, ObjectGuid::LowType spawnId) const;
template<typename T>
bool IsSpawnedObject(uint32 db_guid_or_pool_id) const { return mSpawnedData.IsActiveObject<T>(db_guid_or_pool_id); }
diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp
index 55100ca7396..0c106f69b4a 100644
--- a/src/server/game/Quests/QuestDef.cpp
+++ b/src/server/game/Quests/QuestDef.cpp
@@ -213,15 +213,12 @@ uint32 Quest::XPValue(Player* player) const
else if (diffFactor > 10)
diffFactor = 10;
- uint32 xp = diffFactor * xpentry->Exp[_rewardXPDifficulty] / 10;
- if (xp <= 100)
- xp = 5 * ((xp + 2) / 5);
- else if (xp <= 500)
- xp = 10 * ((xp + 5) / 10);
- else if (xp <= 1000)
- xp = 25 * ((xp + 12) / 25);
- else
- xp = 50 * ((xp + 25) / 50);
+ uint32 xp = RoundXPValue(diffFactor * xpentry->Exp[_rewardXPDifficulty] / 10);
+ if (sWorld->getIntConfig(CONFIG_MIN_QUEST_SCALED_XP_RATIO))
+ {
+ uint32 minScaledXP = RoundXPValue(xpentry->Exp[_rewardXPDifficulty]) * sWorld->getIntConfig(CONFIG_MIN_QUEST_SCALED_XP_RATIO) / 100;
+ xp = std::max(minScaledXP, xp);
+ }
return xp;
}
@@ -447,3 +444,15 @@ void Quest::AddQuestLevelToTitle(std::string &title, int32 level)
questTitlePretty << "[" << level << "] " << title;
title = questTitlePretty.str();
}
+
+uint32 Quest::RoundXPValue(uint32 xp)
+{
+ if (xp <= 100)
+ return 5 * ((xp + 2) / 5);
+ else if (xp <= 500)
+ return 10 * ((xp + 5) / 10);
+ else if (xp <= 1000)
+ return 25 * ((xp + 12) / 25);
+ else
+ return 50 * ((xp + 25) / 50);
+}
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index d2a5e0d5d84..75c5abd7911 100644
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -384,6 +384,9 @@ class TC_GAME_API Quest
uint32 _startItemCount = 0;
uint32 _rewardMailSenderEntry = 0;
uint32 _specialFlags = 0; // custom flags, not sniffed/WDB
+
+ // Helpers
+ static uint32 RoundXPValue(uint32 xp);
};
struct QuestStatusData
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index 9f42ded8cc6..2a26261d9f1 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -955,11 +955,9 @@ private:
// Utility macros for looping over scripts.
#define FOR_SCRIPTS(T, C, E) \
- if (SCR_REG_LST(T).empty()) \
- return; \
- \
- for (SCR_REG_ITR(T) C = SCR_REG_LST(T).begin(); \
- C != SCR_REG_LST(T).end(); ++C)
+ if (!SCR_REG_LST(T).empty()) \
+ for (SCR_REG_ITR(T) C = SCR_REG_LST(T).begin(); \
+ C != SCR_REG_LST(T).end(); ++C)
#define FOR_SCRIPTS_RET(T, C, E, R) \
if (SCR_REG_LST(T).empty()) \
@@ -1566,16 +1564,32 @@ bool ScriptMgr::OnCastItemCombatSpell(Player* player, Unit* victim, SpellInfo co
return tmpscript->OnCastItemCombatSpell(player, victim, spellInfo, item);
}
-bool ScriptMgr::CanSpawn(ObjectGuid::LowType spawnId, uint32 entry, CreatureTemplate const* actTemplate, CreatureData const* cData, Map const* map)
+bool ScriptMgr::CanSpawn(ObjectGuid::LowType spawnId, uint32 entry, CreatureData const* cData, Map const* map)
{
- ASSERT(actTemplate);
-
+ ASSERT(map);
CreatureTemplate const* baseTemplate = sObjectMgr->GetCreatureTemplate(entry);
- if (!baseTemplate)
- baseTemplate = actTemplate;
+ ASSERT(baseTemplate);
+
+ // find out which template we'd be using
+ CreatureTemplate const* actTemplate = baseTemplate;
+ for (uint8 diff = uint8(map->GetSpawnMode()); diff > 0;)
+ {
+ if (uint32 diffEntry = baseTemplate->DifficultyEntry[diff - 1])
+ if (CreatureTemplate const* diffTemplate = sObjectMgr->GetCreatureTemplate(diffEntry))
+ {
+ actTemplate = diffTemplate;
+ break;
+ }
+ if (diff >= RAID_DIFFICULTY_10MAN_HEROIC && map->IsRaid())
+ diff -= 2;
+ else
+ diff -= 1;
+ }
+
uint32 scriptId = baseTemplate->ScriptID;
- if (cData && cData->ScriptId)
- scriptId = cData->ScriptId;
+ if (cData && cData->scriptId)
+ scriptId = cData->scriptId;
+
GET_SCRIPT_RET(CreatureScript, scriptId, tmpscript, true);
return tmpscript->CanSpawn(spawnId, entry, baseTemplate, actTemplate, cData, map);
}
@@ -2215,6 +2229,21 @@ AreaTriggerScript::AreaTriggerScript(char const* name)
ScriptRegistry<AreaTriggerScript>::Instance()->AddScript(this);
}
+bool OnlyOnceAreaTriggerScript::OnTrigger(Player* player, AreaTriggerEntry const* trigger)
+{
+ uint32 const triggerId = trigger->id;
+ if (InstanceScript* instance = player->GetInstanceScript())
+ {
+ if (instance->IsAreaTriggerDone(triggerId))
+ return true;
+ else
+ instance->MarkAreaTriggerDone(triggerId);
+ }
+ return _OnTrigger(player, trigger);
+}
+void OnlyOnceAreaTriggerScript::ResetAreaTriggerDone(InstanceScript* script, uint32 triggerId) { script->ResetAreaTriggerDone(triggerId); }
+void OnlyOnceAreaTriggerScript::ResetAreaTriggerDone(Player const* player, AreaTriggerEntry const* trigger) { if (InstanceScript* instance = player->GetInstanceScript()) ResetAreaTriggerDone(instance, trigger->id); }
+
BattlegroundScript::BattlegroundScript(char const* name)
: ScriptObject(name)
{
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index 311a7faf911..d801aba496d 100644
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -448,6 +448,19 @@ class TC_GAME_API AreaTriggerScript : public ScriptObject
virtual bool OnTrigger(Player* /*player*/, AreaTriggerEntry const* /*trigger*/) { return false; }
};
+class TC_GAME_API OnlyOnceAreaTriggerScript : public AreaTriggerScript
+{
+ using AreaTriggerScript::AreaTriggerScript;
+
+ public:
+ bool OnTrigger(Player* /*player*/, AreaTriggerEntry const* /*trigger*/) override;
+
+ protected:
+ virtual bool _OnTrigger(Player* /*player*/, AreaTriggerEntry const* /*trigger*/) = 0;
+ void ResetAreaTriggerDone(InstanceScript* /*instance*/, uint32 /*triggerId*/);
+ void ResetAreaTriggerDone(Player const* /*player*/, AreaTriggerEntry const* /*trigger*/);
+};
+
class TC_GAME_API BattlegroundScript : public ScriptObject
{
protected:
@@ -907,7 +920,7 @@ class TC_GAME_API ScriptMgr
public: /* CreatureScript */
- bool CanSpawn(ObjectGuid::LowType spawnId, uint32 entry, CreatureTemplate const* actTemplate, CreatureData const* cData, Map const* map);
+ bool CanSpawn(ObjectGuid::LowType spawnId, uint32 entry, CreatureData const* cData, Map const* map);
CreatureAI* GetCreatureAI(Creature* creature);
public: /* GameObjectScript */
@@ -1053,6 +1066,61 @@ class TC_GAME_API ScriptMgr
std::string _currentContext;
};
+template <class S>
+class GenericSpellScriptLoader : public SpellScriptLoader
+{
+ public:
+ GenericSpellScriptLoader(char const* name) : SpellScriptLoader(name) { }
+ SpellScript* GetSpellScript() const override { return new S(); }
+};
+#define RegisterSpellScript(spell_script) new GenericSpellScriptLoader<spell_script>(#spell_script)
+
+template <class A>
+class GenericAuraScriptLoader : public SpellScriptLoader
+{
+ public:
+ GenericAuraScriptLoader(char const* name) : SpellScriptLoader(name) { }
+ AuraScript* GetAuraScript() const override { return new A(); }
+};
+#define RegisterAuraScript(aura_script) new GenericAuraScriptLoader<aura_script>(#aura_script)
+
+template <class S, class A>
+class GenericSpellAndAuraScriptLoader : public SpellScriptLoader
+{
+ public:
+ GenericSpellAndAuraScriptLoader(char const* name) : SpellScriptLoader(name) { }
+ SpellScript* GetSpellScript() const override { return new S(); }
+ AuraScript* GetAuraScript() const override { return new A(); }
+};
+#define RegisterSpellAndAuraScriptPair(spell_script, aura_script) new GenericSpellAndAuraScriptLoader<spell_script, aura_script>(#spell_script)
+
+template <class AI>
+class GenericCreatureScript : public CreatureScript
+{
+ public:
+ GenericCreatureScript(char const* name) : CreatureScript(name) { }
+ CreatureAI* GetAI(Creature* me) const override { return new AI(me); }
+};
+#define RegisterCreatureAI(ai_name) new GenericCreatureScript<ai_name>(#ai_name)
+
+template <class AI, AI*(*AIFactory)(Creature*)>
+class FactoryCreatureScript : public CreatureScript
+{
+ public:
+ FactoryCreatureScript(char const* name) : CreatureScript(name) { }
+ CreatureAI* GetAI(Creature* me) const override { return AIFactory(me); }
+};
+#define RegisterCreatureAIWithFactory(ai_name, factory_fn) new FactoryCreatureScript<ai_name, &factory_fn>(#ai_name)
+
+template <class AI>
+class GenericGameObjectScript : public GameObjectScript
+{
+ public:
+ GenericGameObjectScript(char const* name) : GameObjectScript(name) { }
+ GameObjectAI* GetAI(GameObject* go) const override { return new AI(go); }
+};
+#define RegisterGameObjectAI(ai_name) new GenericGameObjectScript<ai_name>(#ai_name)
+
#define sScriptMgr ScriptMgr::instance()
#endif
diff --git a/src/server/game/Scripting/ScriptSystem.cpp b/src/server/game/Scripting/ScriptSystem.cpp
index 1b4ad6b98d5..b814229151a 100644
--- a/src/server/game/Scripting/ScriptSystem.cpp
+++ b/src/server/game/Scripting/ScriptSystem.cpp
@@ -37,17 +37,17 @@ void SystemMgr::LoadScriptWaypoints()
{
uint32 oldMSTime = getMSTime();
- // Drop Existing Waypoint list
- m_mPointMoveMap.clear();
+ // drop Existing Waypoint list
+ _waypointStore.clear();
- uint64 uiCreatureCount = 0;
+ uint64 entryCount = 0;
- // Load Waypoints
+ // load Waypoints
QueryResult result = WorldDatabase.Query("SELECT COUNT(entry) FROM script_waypoint GROUP BY entry");
if (result)
- uiCreatureCount = result->GetRowCount();
+ entryCount = result->GetRowCount();
- TC_LOG_INFO("server.loading", "Loading Script Waypoints for " UI64FMTD " creature(s)...", uiCreatureCount);
+ TC_LOG_INFO("server.loading", "Loading Script Waypoints for " UI64FMTD " creature(s)...", entryCount);
// 0 1 2 3 4 5
result = WorldDatabase.Query("SELECT entry, pointid, location_x, location_y, location_z, waittime FROM script_waypoint ORDER BY pointid");
@@ -61,29 +61,28 @@ void SystemMgr::LoadScriptWaypoints()
do
{
- Field* pFields = result->Fetch();
- ScriptPointMove temp;
-
- temp.uiCreatureEntry = pFields[0].GetUInt32();
- uint32 uiEntry = temp.uiCreatureEntry;
- temp.uiPointId = pFields[1].GetUInt32();
- temp.fX = pFields[2].GetFloat();
- temp.fY = pFields[3].GetFloat();
- temp.fZ = pFields[4].GetFloat();
- temp.uiWaitTime = pFields[5].GetUInt32();
-
- CreatureTemplate const* pCInfo = sObjectMgr->GetCreatureTemplate(temp.uiCreatureEntry);
-
- if (!pCInfo)
+ Field* fields = result->Fetch();
+ uint32 entry = fields[0].GetUInt32();
+ uint32 id = fields[1].GetUInt32();
+ float x = fields[2].GetFloat();
+ float y = fields[3].GetFloat();
+ float z = fields[4].GetFloat();
+ uint32 waitTime = fields[5].GetUInt32();
+
+ CreatureTemplate const* info = sObjectMgr->GetCreatureTemplate(entry);
+ if (!info)
{
- TC_LOG_ERROR("sql.sql", "TSCR: DB table script_waypoint has waypoint for non-existant creature entry %u", temp.uiCreatureEntry);
+ TC_LOG_ERROR("sql.sql", "SystemMgr: DB table script_waypoint has waypoint for non-existant creature entry %u", entry);
continue;
}
- if (!pCInfo->ScriptID)
- TC_LOG_ERROR("sql.sql", "TSCR: DB table script_waypoint has waypoint for creature entry %u, but creature does not have ScriptName defined and then useless.", temp.uiCreatureEntry);
+ if (!info->ScriptID)
+ TC_LOG_ERROR("sql.sql", "SystemMgr: DB table script_waypoint has waypoint for creature entry %u, but creature does not have ScriptName defined and then useless.", entry);
+
+ WaypointPath& path = _waypointStore[entry];
+ path.id = entry;
+ path.nodes.emplace_back(id, x, y, z, 0.f, waitTime);
- m_mPointMoveMap[uiEntry].push_back(temp);
++count;
} while (result->NextRow());
@@ -163,6 +162,15 @@ void SystemMgr::LoadScriptSplineChains()
}
}
+WaypointPath const* SystemMgr::GetPath(uint32 creatureEntry) const
+{
+ auto itr = _waypointStore.find(creatureEntry);
+ if (itr == _waypointStore.end())
+ return nullptr;
+
+ return &itr->second;
+}
+
std::vector<SplineChainLink> const* SystemMgr::GetSplineChain(uint32 entry, uint16 chainId) const
{
auto it = m_mSplineChainsMap.find({ entry, chainId });
diff --git a/src/server/game/Scripting/ScriptSystem.h b/src/server/game/Scripting/ScriptSystem.h
index 7828c24d680..5b42c5b5a25 100644
--- a/src/server/game/Scripting/ScriptSystem.h
+++ b/src/server/game/Scripting/ScriptSystem.h
@@ -21,59 +21,37 @@
#include "Define.h"
#include "Hash.h"
+#include "WaypointDefines.h"
#include <unordered_map>
#include <vector>
class Creature;
struct SplineChainLink;
-#define TEXT_SOURCE_RANGE -1000000 //the amount of entries each text source has available
-
-struct ScriptPointMove
-{
- uint32 uiCreatureEntry;
- uint32 uiPointId;
- float fX;
- float fY;
- float fZ;
- uint32 uiWaitTime;
-};
-
-typedef std::vector<ScriptPointMove> ScriptPointVector;
-
class TC_GAME_API SystemMgr
{
- private:
- SystemMgr();
- ~SystemMgr();
- SystemMgr(SystemMgr const&) = delete;
- SystemMgr& operator=(SystemMgr const&) = delete;
-
public:
static SystemMgr* instance();
- typedef std::unordered_map<uint32, ScriptPointVector> PointMoveMap;
-
- //Database
+ // database
void LoadScriptWaypoints();
void LoadScriptSplineChains();
- ScriptPointVector const* GetPointMoveList(uint32 creatureEntry) const
- {
- PointMoveMap::const_iterator itr = m_mPointMoveMap.find(creatureEntry);
-
- if (itr == m_mPointMoveMap.end())
- return nullptr;
-
- return &itr->second;
- }
+ WaypointPath const* GetPath(uint32 creatureEntry) const;
std::vector<SplineChainLink> const* GetSplineChain(uint32 entry, uint16 chainId) const;
std::vector<SplineChainLink> const* GetSplineChain(Creature const* who, uint16 id) const;
- protected:
- PointMoveMap m_mPointMoveMap; //coordinates for waypoints
+ private:
typedef std::pair<uint32, uint16> ChainKeyType; // creature entry + chain ID
+
+ SystemMgr();
+ ~SystemMgr();
+
+ SystemMgr(SystemMgr const&) = delete;
+ SystemMgr& operator=(SystemMgr const&) = delete;
+
+ std::unordered_map<uint32, WaypointPath> _waypointStore;
std::unordered_map<ChainKeyType, std::vector<SplineChainLink>> m_mSplineChainsMap; // spline chains
};
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index 05f69568507..a5a4f9139b2 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -273,7 +273,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
///- Before we process anything:
/// If necessary, kick the player because the client didn't send anything for too long
/// (or they've been idling in character select)
- if (IsConnectionIdle())
+ if (IsConnectionIdle() && !HasPermission(rbac::RBAC_PERM_IGNORE_IDLE_CONNECTION))
m_Socket->CloseSocket();
///- Retrieve packets from the receive queue and call the appropriate handlers
diff --git a/src/server/game/Skills/SkillDiscovery.cpp b/src/server/game/Skills/SkillDiscovery.cpp
index 44d9a6a153f..722b5427c72 100644
--- a/src/server/game/Skills/SkillDiscovery.cpp
+++ b/src/server/game/Skills/SkillDiscovery.cpp
@@ -56,7 +56,7 @@ void LoadSkillDiscoveryTable()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 skill discovery definitions. DB table `skill_discovery_template` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 skill discovery definitions. DB table `skill_discovery_template` is empty.");
return;
}
diff --git a/src/server/game/Skills/SkillExtraItems.cpp b/src/server/game/Skills/SkillExtraItems.cpp
index 3b066e71b8b..91e4ea0d244 100644
--- a/src/server/game/Skills/SkillExtraItems.cpp
+++ b/src/server/game/Skills/SkillExtraItems.cpp
@@ -61,7 +61,7 @@ void LoadSkillPerfectItemTable()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 spell perfection definitions. DB table `skill_perfect_item_template` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 spell perfection definitions. DB table `skill_perfect_item_template` is empty.");
return;
}
@@ -148,7 +148,7 @@ void LoadSkillExtraItemTable()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 spell specialization definitions. DB table `skill_extra_item_template` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 spell specialization definitions. DB table `skill_extra_item_template` is empty.");
return;
}
@@ -208,9 +208,6 @@ bool CanCreatePerfectItem(Player* player, uint32 spellId, float &perfectCreateCh
return false;
SkillPerfectItemEntry const* thisEntry = &ret->second;
- // lack of entry means no perfection proc possible
- if (!thisEntry)
- return false;
// if you don't have the spell needed, then no procs for you
if (!player->HasSpell(thisEntry->requiredSpecialization))
@@ -233,10 +230,6 @@ bool CanCreateExtraItems(Player* player, uint32 spellId, float &additionalChance
SkillExtraItemEntry const* specEntry = &ret->second;
- // if no entry, then no extra items can be created
- if (!specEntry)
- return false;
-
// the player doesn't have the required specialization, return false
if (!player->HasSpell(specEntry->requiredSpecialization))
return false;
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 2d57d1472b4..80565e1b464 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -4563,7 +4563,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
break;
case 52172: // Coyote Spirit Despawn Aura
case 60244: // Blood Parrot Despawn Aura
- target->CastSpell((Unit*)nullptr, GetAmount(), true, nullptr, this);
+ target->CastSpell(nullptr, GetAmount(), true, nullptr, this);
break;
case 58600: // Restricted Flight Area
case 58730: // Restricted Flight Area
@@ -5121,7 +5121,7 @@ void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const
}
case 62292: // Blaze (Pool of Tar)
// should we use custom damage?
- target->CastSpell((Unit*)nullptr, m_spellInfo->Effects[m_effIndex].TriggerSpell, true);
+ target->CastSpell(nullptr, m_spellInfo->Effects[m_effIndex].TriggerSpell, true);
break;
case 62399: // Overload Circuit
if (target->GetMap()->IsDungeon() && int(target->GetAppliedAuras().count(62399)) >= (target->GetMap()->IsHeroic() ? 4 : 2))
@@ -5145,7 +5145,7 @@ void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const
// Mirror Image
if (GetId() == 55342)
// Set name of summons to name of caster
- target->CastSpell((Unit*)nullptr, m_spellInfo->Effects[m_effIndex].TriggerSpell, true);
+ target->CastSpell(nullptr, m_spellInfo->Effects[m_effIndex].TriggerSpell, true);
break;
}
case SPELLFAMILY_DRUID:
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index cff25bc8e2c..7c1cdc56de0 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -947,6 +947,9 @@ bool Aura::CanBeSaved() const
if (IsPassive())
return false;
+ if (GetSpellInfo()->IsChanneled())
+ return false;
+
// Check if aura is single target, not only spell info
if (GetCasterGUID() != GetOwner()->GetGUID())
if (GetSpellInfo()->IsSingleTarget() || IsSingleTarget())
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index e56c573a43c..334e51eeb56 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -549,6 +549,7 @@ m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerO
m_referencedFromCurrentSpell = false;
m_executedCurrently = false;
m_needComboPoints = m_spellInfo->NeedsComboPoints();
+ m_comboTarget = nullptr;
m_comboPointGain = 0;
m_delayStart = 0;
m_delayAtDamageCount = 0;
@@ -1399,12 +1400,9 @@ void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplici
default:
{
float angle = targetType.CalcDirectionAngle();
- float objSize = target->GetCombatReach();
- float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster);
- if (dist < objSize)
- dist = objSize;
- else if (targetType.GetTarget() == TARGET_DEST_TARGET_RANDOM)
- dist = objSize + (dist - objSize) * float(rand_norm());
+ float dist = m_spellInfo->Effects[effIndex].CalcRadius(nullptr);
+ if (targetType.GetTarget() == TARGET_DEST_TARGET_RANDOM)
+ dist *= float(rand_norm());
Position pos = dest._position;
target->MovePositionToFirstCollision(pos, dist, angle);
@@ -2551,7 +2549,8 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
// for delayed spells ignore negative spells (after duel end) for friendly targets
/// @todo this cause soul transfer bugged
// 63881 - Malady of the Mind jump spell (Yogg-Saron)
- if (m_spellInfo->Speed > 0.0f && unit->GetTypeId() == TYPEID_PLAYER && !m_spellInfo->IsPositive() && m_spellInfo->Id != 63881)
+ // 45034 - Curse of Boundless Agony jump spell (Kalecgos)
+ if (m_spellInfo->Speed > 0.0f && unit->GetTypeId() == TYPEID_PLAYER && !m_spellInfo->IsPositive() && m_spellInfo->Id != 63881 && m_spellInfo->Id != 45034)
return SPELL_MISS_EVADE;
// assisting case, healing and resurrection
@@ -7881,7 +7880,7 @@ bool WorldObjectSpellAreaTargetCheck::operator()(WorldObject* target)
if (!isInsideCylinder)
return false;
}
-
+
return WorldObjectSpellTargetCheck::operator ()(target);
}
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 852e34a059f..75c97b005af 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -821,27 +821,6 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex)
m_caster->CastSpell(unitTarget, spell->Id, true);
return;
}
- // Cloak of Shadows
- case 35729:
- {
- uint32 dispelMask = SpellInfo::GetDispelMask(DISPEL_ALL);
- Unit::AuraApplicationMap& Auras = unitTarget->GetAppliedAuras();
- for (Unit::AuraApplicationMap::iterator iter = Auras.begin(); iter != Auras.end();)
- {
- // remove all harmful spells on you...
- SpellInfo const* spell = iter->second->GetBase()->GetSpellInfo();
- if (((spell->DmgClass == SPELL_DAMAGE_CLASS_MAGIC && spell->GetSchoolMask() != SPELL_SCHOOL_MASK_NORMAL) // only affect magic spells
- || (spell->GetDispelMask() & dispelMask)) &&
- // ignore positive and passive auras
- !iter->second->IsPositive() && !iter->second->GetBase()->IsPassive())
- {
- m_caster->RemoveAura(iter);
- }
- else
- ++iter;
- }
- return;
- }
}
}
@@ -1008,7 +987,7 @@ void Spell::EffectTriggerRitualOfSummoning(SpellEffIndex effIndex)
finish();
- m_caster->CastSpell((Unit*)nullptr, spellInfo, false);
+ m_caster->CastSpell(nullptr, spellInfo, false);
}
void Spell::EffectJump(SpellEffIndex effIndex)
@@ -2818,8 +2797,6 @@ void Spell::EffectEnchantItemTmp(SpellEffIndex effIndex)
}
return;
}
- if (!itemTarget)
- return;
uint32 enchant_id = m_spellInfo->Effects[effIndex].MiscValue;
@@ -3209,7 +3186,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
// Mangle (Cat): CP
if (m_spellInfo->SpellFamilyFlags[1] & 0x400)
AddComboPointGain(unitTarget, 1);
-
+
// Shred, Maul - Rend and Tear
else if (m_spellInfo->SpellFamilyFlags[0] & 0x00008800 && unitTarget->HasAuraState(AURA_STATE_BLEEDING))
{
@@ -3946,6 +3923,9 @@ void Spell::EffectSanctuary(SpellEffIndex /*effIndex*/)
if (!unitTarget)
return;
+ if (unitTarget->GetTypeId() == TYPEID_PLAYER)
+ unitTarget->ToPlayer()->SendAttackSwingCancelAttack(); // melee and ranged forced attack cancel
+
unitTarget->getHostileRefManager().UpdateVisibility();
Unit::AttackerSet const& attackers = unitTarget->getAttackers();
@@ -4655,9 +4635,13 @@ void Spell::EffectChargeDest(SpellEffIndex /*effIndex*/)
if (m_targets.HasDst())
{
Position pos = destTarget->GetPosition();
- float angle = m_caster->GetRelativeAngle(pos.GetPositionX(), pos.GetPositionY());
- float dist = m_caster->GetDistance(pos);
- pos = m_caster->GetFirstCollisionPosition(dist, angle);
+
+ if (!m_caster->IsWithinLOS(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()))
+ {
+ float angle = m_caster->GetRelativeAngle(pos.GetPositionX(), pos.GetPositionY());
+ float dist = m_caster->GetDistance(pos);
+ pos = m_caster->GetFirstCollisionPosition(dist, angle);
+ }
m_caster->GetMotionMaster()->MoveCharge(pos.m_positionX, pos.m_positionY, pos.m_positionZ);
}
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 9e393f2fcad..e2946dbb45e 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -323,7 +323,7 @@ SpellImplicitTargetInfo::StaticData SpellImplicitTargetInfo::_data[TOTAL_SPELL_
{TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 107 TARGET_UNK_DEST_AREA_UNK_107
{TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 108 TARGET_GAMEOBJECT_CONE
{TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 109
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 110 TARGET_DEST_UNK_110
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_ENTRY, TARGET_DIR_NONE}, // 110 TARGET_UNIT_CONE_ENTRY_110
};
SpellEffectInfo::SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* spellInfo, uint8 effIndex)
@@ -1345,10 +1345,9 @@ bool SpellInfo::CanPierceImmuneAura(SpellInfo const* auraSpellInfo) const
if (HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE) || HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE))
{
// ...but not these (Divine shield, Ice block, Cyclone and Banish for example)
- if (!auraSpellInfo ||
- (auraSpellInfo->Mechanic != MECHANIC_IMMUNE_SHIELD &&
- auraSpellInfo->Mechanic != MECHANIC_INVULNERABILITY &&
- (auraSpellInfo->Mechanic != MECHANIC_BANISH || (IsRankOf(auraSpellInfo) && auraSpellInfo->Dispel != DISPEL_NONE)))) // Banish shouldn't be immune to itself, but Cyclone should
+ if (auraSpellInfo->Mechanic != MECHANIC_IMMUNE_SHIELD &&
+ auraSpellInfo->Mechanic != MECHANIC_INVULNERABILITY &&
+ (auraSpellInfo->Mechanic != MECHANIC_BANISH || (IsRankOf(auraSpellInfo) && auraSpellInfo->Dispel != DISPEL_NONE))) // Banish shouldn't be immune to itself, but Cyclone should
return true;
}
@@ -1370,7 +1369,8 @@ bool SpellInfo::CanDispelAura(SpellInfo const* auraSpellInfo) const
return true;
// These auras (Cyclone for example) are not dispelable
- if (auraSpellInfo->HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE) || auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE))
+ if ((auraSpellInfo->HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE) && auraSpellInfo->Mechanic != MECHANIC_NONE)
+ || auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE))
return false;
return true;
@@ -2877,13 +2877,7 @@ void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, uint8 effIndex, bool app
target->ApplySpellImmune(Id, IMMUNITY_MECHANIC, i, apply);
if (apply && HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
- {
- // exception for purely snare mechanic (eg. hands of freedom)!
- if (mechanicImmunity == (1 << MECHANIC_SNARE))
- target->RemoveMovementImpairingAuras(false);
- else
- target->RemoveAurasWithMechanic(mechanicImmunity, AURA_REMOVE_BY_DEFAULT, Id);
- }
+ target->RemoveAurasWithMechanic(mechanicImmunity, AURA_REMOVE_BY_DEFAULT, Id);
}
if (uint32 dispelImmunity = immuneInfo->DispelImmune)
@@ -3372,6 +3366,8 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const
{
case 29214: // Wrath of the Plaguebringer
case 34700: // Allergic Reaction
+ case 41914: // Parasitic Shadowfiend (Illidan)
+ case 41917: // Parasitic Shadowfiend (Illidan)
case 54836: // Wrath of the Plaguebringer
case 61987: // Avenging Wrath Marker
case 61988: // Divine Shield exclude aura
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index fc7b219d54d..22b16a29dde 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3898,6 +3898,12 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_100_YARDS); // 100yd
});
+ // Coldflame (Lord Marrowgar)
+ ApplySpellFix({ 69146, 70823, 70824, 70825 }, [](SpellInfo* spellInfo)
+ {
+ spellInfo->AttributesEx4 &= ~SPELL_ATTR4_IGNORE_RESISTANCES;
+ });
+
// Shadow's Fate
ApplySpellFix({ 71169 }, [](SpellInfo* spellInfo)
{
@@ -4127,13 +4133,13 @@ void SpellMgr::LoadSpellInfoCorrections()
// Summon Shadow Trap
ApplySpellFix({ 73540 }, [](SpellInfo* spellInfo)
{
- spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(23); // 90 seconds
+ spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(3); // 60 seconds
});
// Shadow Trap (visual)
ApplySpellFix({ 73530 }, [](SpellInfo* spellInfo)
{
- spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(28); // 5 seconds
+ spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(27); // 3 seconds
});
// Shadow Trap
@@ -4459,6 +4465,18 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->ProcFlags = 0;
});
+ // Shadowstep
+ ApplySpellFix({ 36563 }, [](SpellInfo* spellInfo)
+ {
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_4_YARDS); // 4yd
+ });
+
+ // Feral Charge - Cat
+ ApplySpellFix({ 49376 }, [](SpellInfo* spellInfo)
+ {
+ spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_3_YARDS); // 3yd
+ });
+
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
{
SpellInfo* spellInfo = mSpellInfoMap[i];
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index 03f06961a4b..7e63770c3e1 100644
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -786,13 +786,13 @@ class TC_GAME_API AuraScript : public _SpellScript
HookList<EffectAbsorbHandler> AfterEffectAbsorb;
// executed when mana shield aura effect is going to reduce damage
- // example: OnEffectManaShield += AuraEffectAbsorbFn(class::function, EffectIndexSpecifier);
+ // example: OnEffectManaShield += AuraEffectManaShieldFn(class::function, EffectIndexSpecifier);
// where function is: void function (AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount);
HookList<EffectManaShieldHandler> OnEffectManaShield;
#define AuraEffectManaShieldFn(F, I) EffectManaShieldFunction(&F, I)
// executed after mana shield aura effect reduced damage to target - absorbAmount is real amount absorbed by aura
- // example: AfterEffectManaShield += AuraEffectAbsorbFn(class::function, EffectIndexSpecifier);
+ // example: AfterEffectManaShield += AuraEffectManaShieldFn(class::function, EffectIndexSpecifier);
// where function is: void function (AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount);
HookList<EffectManaShieldHandler> AfterEffectManaShield;
diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp
index 0357fcc4e15..6bcf3128427 100644
--- a/src/server/game/Tools/PlayerDump.cpp
+++ b/src/server/game/Tools/PlayerDump.cpp
@@ -936,7 +936,7 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s
if (!ChangeColumn(ts, line, "at_login", "1"))
return DUMP_FILE_BROKEN;
}
- else if (!ChangeColumn(ts, line, "name", name.c_str())) // characters.name
+ else if (!ChangeColumn(ts, line, "name", name)) // characters.name
return DUMP_FILE_BROKEN;
break;
}
diff --git a/src/server/game/Warden/WardenCheckMgr.cpp b/src/server/game/Warden/WardenCheckMgr.cpp
index 3b8387e3381..5a7a6bf49dd 100644
--- a/src/server/game/Warden/WardenCheckMgr.cpp
+++ b/src/server/game/Warden/WardenCheckMgr.cpp
@@ -38,6 +38,8 @@ WardenCheckMgr::~WardenCheckMgr()
void WardenCheckMgr::LoadWardenChecks()
{
+ uint32 oldMSTime = getMSTime();
+
// Check if Warden is enabled by config before loading anything
if (!sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED))
{
@@ -141,11 +143,13 @@ void WardenCheckMgr::LoadWardenChecks()
}
while (result->NextRow());
- TC_LOG_INFO("server.loading", ">> Loaded %u warden checks.", count);
+ TC_LOG_INFO("server.loading", ">> Loaded %u warden checks in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
void WardenCheckMgr::LoadWardenOverrides()
{
+ uint32 oldMSTime = getMSTime();
+
// Check if Warden is enabled by config before loading anything
if (!sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED))
{
@@ -187,7 +191,7 @@ void WardenCheckMgr::LoadWardenOverrides()
}
while (result->NextRow());
- TC_LOG_INFO("server.loading", ">> Loaded %u warden action overrides.", count);
+ TC_LOG_INFO("server.loading", ">> Loaded %u warden action overrides in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
WardenCheckMgr* WardenCheckMgr::instance()
diff --git a/src/server/game/Weather/WeatherMgr.cpp b/src/server/game/Weather/WeatherMgr.cpp
index 95728b7e8ae..98fbf897e27 100644
--- a/src/server/game/Weather/WeatherMgr.cpp
+++ b/src/server/game/Weather/WeatherMgr.cpp
@@ -95,7 +95,7 @@ void LoadWeatherData()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 weather definitions. DB table `game_weather` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 weather definitions. DB table `game_weather` is empty.");
return;
}
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index ae5cc87d097..03081a113de 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -81,7 +81,7 @@
#include "VMapFactory.h"
#include "VMapManager2.h"
#include "WardenCheckMgr.h"
-#include "WaypointMovementGenerator.h"
+#include "WaypointManager.h"
#include "WeatherMgr.h"
#include "WhoListStorage.h"
#include "WorldSession.h"
@@ -134,6 +134,11 @@ World::World()
memset(m_int_configs, 0, sizeof(m_int_configs));
memset(m_bool_configs, 0, sizeof(m_bool_configs));
memset(m_float_configs, 0, sizeof(m_float_configs));
+
+ _guidWarn = false;
+ _guidAlert = false;
+ _warnDiff = 0;
+ _warnShutdownTime = time(NULL);
}
/// World destructor
@@ -196,6 +201,59 @@ void World::SetClosed(bool val)
sScriptMgr->OnOpenStateChange(!val);
}
+void World::TriggerGuidWarning()
+{
+ // Lock this only to prevent multiple maps triggering at the same time
+ std::lock_guard<std::mutex> lock(_guidAlertLock);
+
+ time_t gameTime = GameTime::GetGameTime();
+ time_t today = (gameTime / DAY) * DAY;
+
+ // Check if our window to restart today has passed. 5 mins until quiet time
+ while (gameTime >= (today + (getIntConfig(CONFIG_RESPAWN_RESTARTQUIETTIME) * HOUR) - 1810))
+ today += DAY;
+
+ // Schedule restart for 30 minutes before quiet time, or as long as we have
+ _warnShutdownTime = today + (getIntConfig(CONFIG_RESPAWN_RESTARTQUIETTIME) * HOUR) - 1800;
+
+ _guidWarn = true;
+ SendGuidWarning();
+}
+
+void World::TriggerGuidAlert()
+{
+ // Lock this only to prevent multiple maps triggering at the same time
+ std::lock_guard<std::mutex> lock(_guidAlertLock);
+
+ DoGuidAlertRestart();
+ _guidAlert = true;
+ _guidWarn = false;
+}
+
+void World::DoGuidWarningRestart()
+{
+ if (m_ShutdownTimer)
+ return;
+
+ ShutdownServ(1800, SHUTDOWN_MASK_RESTART, RESTART_EXIT_CODE);
+ _warnShutdownTime += HOUR;
+}
+
+void World::DoGuidAlertRestart()
+{
+ if (m_ShutdownTimer)
+ return;
+
+ ShutdownServ(300, SHUTDOWN_MASK_RESTART, RESTART_EXIT_CODE, _alertRestartReason);
+}
+
+void World::SendGuidWarning()
+{
+ if (!m_ShutdownTimer && _guidWarn && getIntConfig(CONFIG_RESPAWN_GUIDWARNING_FREQUENCY) > 0)
+ SendServerMessage(SERVER_MSG_STRING, _guidWarningMsg.c_str());
+ _warnDiff = 0;
+}
+
/// Find a session by its id
WorldSession* World::FindSession(uint32 id) const
{
@@ -670,6 +728,27 @@ void World::LoadConfigSettings(bool reload)
m_float_configs[CONFIG_GROUP_XP_DISTANCE] = sConfigMgr->GetFloatDefault("MaxGroupXPDistance", 74.0f);
m_float_configs[CONFIG_MAX_RECRUIT_A_FRIEND_DISTANCE] = sConfigMgr->GetFloatDefault("MaxRecruitAFriendBonusDistance", 100.0f);
+ m_int_configs[CONFIG_MIN_QUEST_SCALED_XP_RATIO] = sConfigMgr->GetIntDefault("MinQuestScaledXPRatio", 0);
+ if (m_int_configs[CONFIG_MIN_QUEST_SCALED_XP_RATIO] > 100)
+ {
+ TC_LOG_ERROR("server.loading", "MinQuestScaledXPRatio (%i) must be in range 0..100. Set to 0.", m_int_configs[CONFIG_MIN_QUEST_SCALED_XP_RATIO]);
+ m_int_configs[CONFIG_MIN_QUEST_SCALED_XP_RATIO] = 0;
+ }
+
+ m_int_configs[CONFIG_MIN_CREATURE_SCALED_XP_RATIO] = sConfigMgr->GetIntDefault("MinCreatureScaledXPRatio", 0);
+ if (m_int_configs[CONFIG_MIN_CREATURE_SCALED_XP_RATIO] > 100)
+ {
+ TC_LOG_ERROR("server.loading", "MinCreatureScaledXPRatio (%i) must be in range 0..100. Set to 0.", m_int_configs[CONFIG_MIN_CREATURE_SCALED_XP_RATIO]);
+ m_int_configs[CONFIG_MIN_CREATURE_SCALED_XP_RATIO] = 0;
+ }
+
+ m_int_configs[CONFIG_MIN_DISCOVERED_SCALED_XP_RATIO] = sConfigMgr->GetIntDefault("MinDiscoveredScaledXPRatio", 0);
+ if (m_int_configs[CONFIG_MIN_DISCOVERED_SCALED_XP_RATIO] > 100)
+ {
+ TC_LOG_ERROR("server.loading", "MinDiscoveredScaledXPRatio (%i) must be in range 0..100. Set to 0.", m_int_configs[CONFIG_MIN_DISCOVERED_SCALED_XP_RATIO]);
+ m_int_configs[CONFIG_MIN_DISCOVERED_SCALED_XP_RATIO] = 0;
+ }
+
/// @todo Add MonsterSight (with meaning) in worldserver.conf or put them as define
m_float_configs[CONFIG_SIGHT_MONSTER] = sConfigMgr->GetFloatDefault("MonsterSight", 50.0f);
@@ -916,6 +995,12 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_GROUP_VISIBILITY] = sConfigMgr->GetIntDefault("Visibility.GroupMode", 1);
m_int_configs[CONFIG_MAIL_DELIVERY_DELAY] = sConfigMgr->GetIntDefault("MailDeliveryDelay", HOUR);
+ m_int_configs[CONFIG_CLEAN_OLD_MAIL_TIME] = sConfigMgr->GetIntDefault("CleanOldMailTime", 4);
+ if (m_int_configs[CONFIG_CLEAN_OLD_MAIL_TIME] > 23)
+ {
+ TC_LOG_ERROR("server.loading", "CleanOldMailTime (%u) must be an hour, between 0 and 23. Set to 4.", m_int_configs[CONFIG_CLEAN_OLD_MAIL_TIME]);
+ m_int_configs[CONFIG_CLEAN_OLD_MAIL_TIME] = 4;
+ }
m_int_configs[CONFIG_UPTIME_UPDATE] = sConfigMgr->GetIntDefault("UpdateUptimeInterval", 10);
if (int32(m_int_configs[CONFIG_UPTIME_UPDATE]) <= 0)
@@ -1192,6 +1277,50 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_NO_GRAY_AGGRO_BELOW] = m_int_configs[CONFIG_NO_GRAY_AGGRO_ABOVE];
}
+ // Respawn Settings
+ m_int_configs[CONFIG_RESPAWN_MINCHECKINTERVALMS] = sConfigMgr->GetIntDefault("Respawn.MinCheckIntervalMS", 5000);
+ m_int_configs[CONFIG_RESPAWN_DYNAMICMODE] = sConfigMgr->GetIntDefault("Respawn.DynamicMode", 0);
+ if (m_int_configs[CONFIG_RESPAWN_DYNAMICMODE] > 1)
+ {
+ TC_LOG_ERROR("server.loading", "Invalid value for Respawn.DynamicMode (%u). Set to 0.", m_int_configs[CONFIG_RESPAWN_DYNAMICMODE]);
+ m_int_configs[CONFIG_RESPAWN_DYNAMICMODE] = 0;
+ }
+ m_bool_configs[CONFIG_RESPAWN_DYNAMIC_ESCORTNPC] = sConfigMgr->GetBoolDefault("Respawn.DynamicEscortNPC", false);
+ m_int_configs[CONFIG_RESPAWN_GUIDWARNLEVEL] = sConfigMgr->GetIntDefault("Respawn.GuidWarnLevel", 12000000);
+ if (m_int_configs[CONFIG_RESPAWN_GUIDWARNLEVEL] > 16777215)
+ {
+ TC_LOG_ERROR("server.loading", "Respawn.GuidWarnLevel (%u) cannot be greater than maximum GUID (16777215). Set to 12000000.", m_int_configs[CONFIG_RESPAWN_GUIDWARNLEVEL]);
+ m_int_configs[CONFIG_RESPAWN_GUIDWARNLEVEL] = 12000000;
+ }
+ m_int_configs[CONFIG_RESPAWN_GUIDALERTLEVEL] = sConfigMgr->GetIntDefault("Respawn.GuidAlertLevel", 16000000);
+ if (m_int_configs[CONFIG_RESPAWN_GUIDALERTLEVEL] > 16777215)
+ {
+ TC_LOG_ERROR("server.loading", "Respawn.GuidWarnLevel (%u) cannot be greater than maximum GUID (16777215). Set to 16000000.", m_int_configs[CONFIG_RESPAWN_GUIDALERTLEVEL]);
+ m_int_configs[CONFIG_RESPAWN_GUIDALERTLEVEL] = 16000000;
+ }
+ m_int_configs[CONFIG_RESPAWN_RESTARTQUIETTIME] = sConfigMgr->GetIntDefault("Respawn.RestartQuietTime", 3);
+ if (m_int_configs[CONFIG_RESPAWN_RESTARTQUIETTIME] > 23)
+ {
+ TC_LOG_ERROR("server.loading", "Respawn.RestartQuietTime (%u) must be an hour, between 0 and 23. Set to 3.", m_int_configs[CONFIG_RESPAWN_RESTARTQUIETTIME]);
+ m_int_configs[CONFIG_RESPAWN_RESTARTQUIETTIME] = 3;
+ }
+ m_float_configs[CONFIG_RESPAWN_DYNAMICRATE_CREATURE] = sConfigMgr->GetFloatDefault("Respawn.DynamicRateCreature", 10.0f);
+ if (m_float_configs[CONFIG_RESPAWN_DYNAMICRATE_CREATURE] < 0.0f)
+ {
+ TC_LOG_ERROR("server.loading", "Respawn.DynamicRateCreature (%f) must be positive. Set to 10.", m_float_configs[CONFIG_RESPAWN_DYNAMICRATE_CREATURE]);
+ m_float_configs[CONFIG_RESPAWN_DYNAMICRATE_CREATURE] = 10.0f;
+ }
+ m_int_configs[CONFIG_RESPAWN_DYNAMICMINIMUM_CREATURE] = sConfigMgr->GetIntDefault("Respawn.DynamicMinimumCreature", 10);
+ m_float_configs[CONFIG_RESPAWN_DYNAMICRATE_GAMEOBJECT] = sConfigMgr->GetFloatDefault("Respawn.DynamicRateGameObject", 10.0f);
+ if (m_float_configs[CONFIG_RESPAWN_DYNAMICRATE_GAMEOBJECT] < 0.0f)
+ {
+ TC_LOG_ERROR("server.loading", "Respawn.DynamicRateGameObject (%f) must be positive. Set to 10.", m_float_configs[CONFIG_RESPAWN_DYNAMICRATE_GAMEOBJECT]);
+ m_float_configs[CONFIG_RESPAWN_DYNAMICRATE_GAMEOBJECT] = 10.0f;
+ }
+ m_int_configs[CONFIG_RESPAWN_DYNAMICMINIMUM_GAMEOBJECT] = sConfigMgr->GetIntDefault("Respawn.DynamicMinimumGameObject", 10);
+ _guidWarningMsg = sConfigMgr->GetStringDefault("Respawn.WarningMessage", "There will be an unscheduled server restart at 03:00. The server will be available again shortly after.");
+ _alertRestartReason = sConfigMgr->GetStringDefault("Respawn.AlertRestartReason", "Urgent Maintenance");
+ m_int_configs[CONFIG_RESPAWN_GUIDWARNING_FREQUENCY] = sConfigMgr->GetIntDefault("Respawn.WarningFrequency", 1800);
///- Read the "Data" directory from the config file
std::string dataPath = sConfigMgr->GetStringDefault("DataDir", "./");
if (dataPath.empty() || (dataPath.at(dataPath.length()-1) != '/' && dataPath.at(dataPath.length()-1) != '\\'))
@@ -1504,6 +1633,7 @@ void World::SetInitialWorldSettings()
sObjectMgr->LoadPageTextLocales();
sObjectMgr->LoadGossipMenuItemsLocales();
sObjectMgr->LoadPointOfInterestLocales();
+ sObjectMgr->LoadQuestGreetingsLocales();
sObjectMgr->SetDBCLocaleIndex(GetDefaultDbcLocale()); // Get once for all the locale index of DBC language (console/broadcasts)
TC_LOG_INFO("server.loading", ">> Localization strings loaded in %u ms", GetMSTimeDiffToNow(oldMSTime));
@@ -1601,6 +1731,12 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading Creature Base Stats...");
sObjectMgr->LoadCreatureClassLevelStats();
+ TC_LOG_INFO("server.loading", "Loading Spawn Group Templates...");
+ sObjectMgr->LoadSpawnGroupTemplates();
+
+ TC_LOG_INFO("server.loading", "Loading instance spawn groups...");
+ sObjectMgr->LoadInstanceSpawnGroups();
+
TC_LOG_INFO("server.loading", "Loading Creature Data...");
sObjectMgr->LoadCreatures();
@@ -1617,10 +1753,13 @@ void World::SetInitialWorldSettings()
sObjectMgr->LoadCreatureAddons(); // must be after LoadCreatureTemplates() and LoadCreatures()
TC_LOG_INFO("server.loading", "Loading Gameobject Data...");
- sObjectMgr->LoadGameobjects();
+ sObjectMgr->LoadGameObjects();
+
+ TC_LOG_INFO("server.loading", "Loading Spawn Group Data...");
+ sObjectMgr->LoadSpawnGroups();
TC_LOG_INFO("server.loading", "Loading GameObject Addon Data...");
- sObjectMgr->LoadGameObjectAddons(); // must be after LoadGameObjectTemplate() and LoadGameobjects()
+ sObjectMgr->LoadGameObjectAddons(); // must be after LoadGameObjectTemplate() and LoadGameObjects()
TC_LOG_INFO("server.loading", "Loading GameObject Quest Items...");
sObjectMgr->LoadGameObjectQuestItems();
@@ -1646,11 +1785,15 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading Quests Starters and Enders...");
sObjectMgr->LoadQuestStartersAndEnders(); // must be after quest load
+ TC_LOG_INFO("server.loading", "Loading Quests Greetings...");
+ sObjectMgr->LoadQuestGreetings(); // must be loaded after creature_template, gameobject_template tables
+
TC_LOG_INFO("server.loading", "Loading Objects Pooling Data...");
sPoolMgr->LoadFromDB();
TC_LOG_INFO("server.loading", "Loading Game Event Data..."); // must be after loading pools fully
- sGameEventMgr->LoadFromDB();
+ sGameEventMgr->LoadHolidayDates(); // Must be after loading DBC
+ sGameEventMgr->LoadFromDB(); // Must be after loading holiday dates
TC_LOG_INFO("server.loading", "Loading UNIT_NPC_FLAG_SPELLCLICK Data..."); // must be after LoadQuests
sObjectMgr->LoadNPCSpellClickSpells();
@@ -1914,7 +2057,8 @@ void World::SetInitialWorldSettings()
tm localTm;
time_t gameTime = GameTime::GetGameTime();
localtime_r(&gameTime, &localTm);
- mail_timer = ((((localTm.tm_hour + 20) % 24)* HOUR * IN_MILLISECONDS) / m_timers[WUPDATE_AUCTIONS].GetInterval());
+ uint8 CleanOldMailsTime = getIntConfig(CONFIG_CLEAN_OLD_MAIL_TIME);
+ mail_timer = ((((localTm.tm_hour + (24 - CleanOldMailsTime)) % 24)* HOUR * IN_MILLISECONDS) / m_timers[WUPDATE_AUCTIONS].GetInterval());
//1440
mail_timer_expires = ((DAY * IN_MILLISECONDS) / (m_timers[WUPDATE_AUCTIONS].GetInterval()));
TC_LOG_INFO("server.loading", "Mail timer set to: " UI64FMTD ", mail return is called every " UI64FMTD " minutes", uint64(mail_timer), uint64(mail_timer_expires));
@@ -2289,6 +2433,16 @@ void World::Update(uint32 diff)
// update the instance reset times
sInstanceSaveMgr->Update();
+ // Check for shutdown warning
+ if (_guidWarn && !_guidAlert)
+ {
+ _warnDiff += diff;
+ if (GameTime::GetGameTime() >= _warnShutdownTime)
+ DoGuidWarningRestart();
+ else if (_warnDiff > getIntConfig(CONFIG_RESPAWN_GUIDWARNING_FREQUENCY) * IN_MILLISECONDS)
+ SendGuidWarning();
+ }
+
// And last, but not least handle the issued cli commands
ProcessCliCommands();
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 5254b32bbdf..8d06620641b 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -202,7 +202,6 @@ enum WorldFloatConfigs
CONFIG_ARENA_WIN_RATING_MODIFIER_2,
CONFIG_ARENA_LOSE_RATING_MODIFIER,
CONFIG_ARENA_MATCHMAKER_RATING_MODIFIER,
- CONFIG_RESPAWN_DYNAMICRADIUS,
CONFIG_RESPAWN_DYNAMICRATE_CREATURE,
CONFIG_RESPAWN_DYNAMICRATE_GAMEOBJECT,
FLOAT_CONFIG_VALUE_COUNT
@@ -251,6 +250,9 @@ enum WorldIntConfigs
CONFIG_DAILY_QUEST_RESET_TIME_HOUR,
CONFIG_MAX_PRIMARY_TRADE_SKILL,
CONFIG_MIN_PETITION_SIGNS,
+ CONFIG_MIN_QUEST_SCALED_XP_RATIO,
+ CONFIG_MIN_CREATURE_SCALED_XP_RATIO,
+ CONFIG_MIN_DISCOVERED_SCALED_XP_RATIO,
CONFIG_GM_LOGIN_STATE,
CONFIG_GM_VISIBLE_STATE,
CONFIG_GM_ACCEPT_TICKETS,
@@ -263,6 +265,7 @@ enum WorldIntConfigs
CONFIG_FORCE_SHUTDOWN_THRESHOLD,
CONFIG_GROUP_VISIBILITY,
CONFIG_MAIL_DELIVERY_DELAY,
+ CONFIG_CLEAN_OLD_MAIL_TIME,
CONFIG_UPTIME_UPDATE,
CONFIG_SKILL_CHANCE_ORANGE,
CONFIG_SKILL_CHANCE_YELLOW,
@@ -379,13 +382,11 @@ enum WorldIntConfigs
CONFIG_AUCTION_GETALL_DELAY,
CONFIG_AUCTION_SEARCH_DELAY,
CONFIG_TALENTS_INSPECTING,
- CONFIG_RESPAWN_MINCELLCHECKMS,
+ CONFIG_RESPAWN_MINCHECKINTERVALMS,
CONFIG_RESPAWN_DYNAMICMODE,
CONFIG_RESPAWN_GUIDWARNLEVEL,
CONFIG_RESPAWN_GUIDALERTLEVEL,
CONFIG_RESPAWN_RESTARTQUIETTIME,
- CONFIG_RESPAWN_ACTIVITYSCOPECREATURE,
- CONFIG_RESPAWN_ACTIVITYSCOPEGAMEOBJECT,
CONFIG_RESPAWN_DYNAMICMINIMUM_CREATURE,
CONFIG_RESPAWN_DYNAMICMINIMUM_GAMEOBJECT,
CONFIG_RESPAWN_GUIDWARNING_FREQUENCY,
@@ -765,6 +766,10 @@ class TC_GAME_API World
void ReloadRBAC();
void RemoveOldCorpses();
+ void TriggerGuidWarning();
+ void TriggerGuidAlert();
+ bool IsGuidWarning() { return _guidWarn; }
+ bool IsGuidAlert() { return _guidAlert; }
protected:
void _UpdateGameTime();
@@ -859,7 +864,21 @@ class TC_GAME_API World
AutobroadcastsWeightMap m_AutobroadcastsWeights;
void ProcessQueryCallbacks();
+
+ void SendGuidWarning();
+ void DoGuidWarningRestart();
+ void DoGuidAlertRestart();
QueryCallbackProcessor _queryProcessor;
+
+ std::string _guidWarningMsg;
+ std::string _alertRestartReason;
+
+ std::mutex _guidAlertLock;
+
+ bool _guidWarn;
+ bool _guidAlert;
+ uint32 _warnDiff;
+ time_t _warnShutdownTime;
};
TC_GAME_API extern Realm realm;
diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt
index 8beb5faacde..3a241fcd95e 100644
--- a/src/server/scripts/CMakeLists.txt
+++ b/src/server/scripts/CMakeLists.txt
@@ -94,7 +94,7 @@ if (USE_SCRIPTPCH)
set(PRIVATE_PCH_SOURCE ScriptPCH.cpp)
if (MSVC)
list(INSERT PRIVATE_SOURCES 0 ScriptPCH.cpp)
- endif (MSVC)
+ endif (MSVC)
endif ()
GroupSources(${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/src/server/scripts/Commands/cs_ban.cpp b/src/server/scripts/Commands/cs_ban.cpp
index 5c390a34e11..137620123a6 100644
--- a/src/server/scripts/Commands/cs_ban.cpp
+++ b/src/server/scripts/Commands/cs_ban.cpp
@@ -587,8 +587,7 @@ public:
static bool HandleBanListIPCommand(ChatHandler* handler, char const* args)
{
- PreparedStatement* stmt = nullptr;
- stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_EXPIRED_IP_BANS);
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_EXPIRED_IP_BANS);
LoginDatabase.Execute(stmt);
char* filterStr = strtok((char*)args, " ");
diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp
index 69f7ecb3f9a..a7ac9028bc8 100644
--- a/src/server/scripts/Commands/cs_debug.cpp
+++ b/src/server/scripts/Commands/cs_debug.cpp
@@ -972,7 +972,7 @@ public:
Map* map = handler->GetSession()->GetPlayer()->GetMap();
- if (!v->Create(map->GenerateLowGuid<HighGuid::Vehicle>(), map, handler->GetSession()->GetPlayer()->GetPhaseMask(), entry, x, y, z, o, nullptr, id))
+ if (!v->Create(map->GenerateLowGuid<HighGuid::Vehicle>(), map, handler->GetSession()->GetPlayer()->GetPhaseMask(), entry, { x, y, z, o }, nullptr, id))
{
delete v;
return false;
diff --git a/src/server/scripts/Commands/cs_disable.cpp b/src/server/scripts/Commands/cs_disable.cpp
index bc80d3d6fd0..b8d1116574d 100644
--- a/src/server/scripts/Commands/cs_disable.cpp
+++ b/src/server/scripts/Commands/cs_disable.cpp
@@ -187,8 +187,7 @@ public:
break;
}
- PreparedStatement* stmt = nullptr;
- stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_DISABLES);
+ PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_DISABLES);
stmt->setUInt32(0, entry);
stmt->setUInt8(1, disableType);
PreparedQueryResult result = WorldDatabase.Query(stmt);
@@ -313,8 +312,7 @@ public:
break;
}
- PreparedStatement* stmt = nullptr;
- stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_DISABLES);
+ PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_DISABLES);
stmt->setUInt32(0, entry);
stmt->setUInt8(1, disableType);
PreparedQueryResult result = WorldDatabase.Query(stmt);
diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp
index 6a27060c2ed..7d0563b2acc 100644
--- a/src/server/scripts/Commands/cs_go.cpp
+++ b/src/server/scripts/Commands/cs_go.cpp
@@ -138,8 +138,6 @@ public:
float o = fields[3].GetFloat();
uint32 mapId = fields[4].GetUInt16();
- Transport* transport = nullptr;
-
if (!MapManager::IsValidMapCoord(mapId, x, y, z, o) || sObjectMgr->IsTransportMap(mapId))
{
handler->PSendSysMessage(LANG_INVALID_TARGET_COORD, x, y, mapId);
@@ -157,11 +155,7 @@ public:
else
player->SaveRecallPosition();
- if (player->TeleportTo(mapId, x, y, z, o))
- {
- if (transport)
- transport->AddPassenger(player);
- }
+ player->TeleportTo(mapId, x, y, z, o);
return true;
}
@@ -272,28 +266,18 @@ public:
if (!guidLow)
return false;
- float x, y, z, o;
- uint32 mapId;
-
// by DB guid
- if (GameObjectData const* goData = sObjectMgr->GetGOData(guidLow))
- {
- x = goData->posX;
- y = goData->posY;
- z = goData->posZ;
- o = goData->orientation;
- mapId = goData->mapid;
- }
- else
+ GameObjectData const* goData = sObjectMgr->GetGameObjectData(guidLow);
+ if (!goData)
{
handler->SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND);
handler->SetSentErrorMessage(true);
return false;
}
- if (!MapManager::IsValidMapCoord(mapId, x, y, z, o) || sObjectMgr->IsTransportMap(mapId))
+ if (!MapManager::IsValidMapCoord(goData->spawnPoint) || sObjectMgr->IsTransportMap(goData->spawnPoint.GetMapId()))
{
- handler->PSendSysMessage(LANG_INVALID_TARGET_COORD, x, y, mapId);
+ handler->PSendSysMessage(LANG_INVALID_TARGET_COORD, goData->spawnPoint.GetPositionX(), goData->spawnPoint.GetPositionY(), goData->spawnPoint.GetMapId());
handler->SetSentErrorMessage(true);
return false;
}
@@ -308,7 +292,7 @@ public:
else
player->SaveRecallPosition();
- player->TeleportTo(mapId, x, y, z, o);
+ player->TeleportTo(goData->spawnPoint);
return true;
}
diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp
index a315355ff44..fd4baf69037 100644
--- a/src/server/scripts/Commands/cs_gobject.cpp
+++ b/src/server/scripts/Commands/cs_gobject.cpp
@@ -38,6 +38,10 @@ EndScriptData */
#include "RBAC.h"
#include "WorldSession.h"
+// definitions are over in cs_npc.cpp
+bool HandleNpcSpawnGroup(ChatHandler* handler, char const* args);
+bool HandleNpcDespawnGroup(ChatHandler* handler, char const* args);
+
class gobject_commandscript : public CommandScript
{
public:
@@ -57,15 +61,17 @@ public:
};
static std::vector<ChatCommand> gobjectCommandTable =
{
- { "activate", rbac::RBAC_PERM_COMMAND_GOBJECT_ACTIVATE, false, &HandleGameObjectActivateCommand, "" },
- { "delete", rbac::RBAC_PERM_COMMAND_GOBJECT_DELETE, false, &HandleGameObjectDeleteCommand, "" },
- { "info", rbac::RBAC_PERM_COMMAND_GOBJECT_INFO, false, &HandleGameObjectInfoCommand, "" },
- { "move", rbac::RBAC_PERM_COMMAND_GOBJECT_MOVE, false, &HandleGameObjectMoveCommand, "" },
- { "near", rbac::RBAC_PERM_COMMAND_GOBJECT_NEAR, false, &HandleGameObjectNearCommand, "" },
- { "target", rbac::RBAC_PERM_COMMAND_GOBJECT_TARGET, false, &HandleGameObjectTargetCommand, "" },
- { "turn", rbac::RBAC_PERM_COMMAND_GOBJECT_TURN, false, &HandleGameObjectTurnCommand, "" },
- { "add", rbac::RBAC_PERM_COMMAND_GOBJECT_ADD, false, nullptr, "", gobjectAddCommandTable },
- { "set", rbac::RBAC_PERM_COMMAND_GOBJECT_SET, false, nullptr, "", gobjectSetCommandTable },
+ { "activate", rbac::RBAC_PERM_COMMAND_GOBJECT_ACTIVATE, false, &HandleGameObjectActivateCommand, "" },
+ { "delete", rbac::RBAC_PERM_COMMAND_GOBJECT_DELETE, false, &HandleGameObjectDeleteCommand, "" },
+ { "info", rbac::RBAC_PERM_COMMAND_GOBJECT_INFO, false, &HandleGameObjectInfoCommand, "" },
+ { "move", rbac::RBAC_PERM_COMMAND_GOBJECT_MOVE, false, &HandleGameObjectMoveCommand, "" },
+ { "near", rbac::RBAC_PERM_COMMAND_GOBJECT_NEAR, false, &HandleGameObjectNearCommand, "" },
+ { "target", rbac::RBAC_PERM_COMMAND_GOBJECT_TARGET, false, &HandleGameObjectTargetCommand, "" },
+ { "turn", rbac::RBAC_PERM_COMMAND_GOBJECT_TURN, false, &HandleGameObjectTurnCommand, "" },
+ { "spawngroup", rbac::RBAC_PERM_COMMAND_GOBJECT_SPAWNGROUP, false, &HandleNpcSpawnGroup, "" },
+ { "despawngroup", rbac::RBAC_PERM_COMMAND_GOBJECT_DESPAWNGROUP, false, &HandleNpcDespawnGroup,""},
+ { "add", rbac::RBAC_PERM_COMMAND_GOBJECT_ADD, false, nullptr, "", gobjectAddCommandTable },
+ { "set", rbac::RBAC_PERM_COMMAND_GOBJECT_SET, false, nullptr, "", gobjectSetCommandTable },
};
static std::vector<ChatCommand> commandTable =
{
@@ -169,14 +175,14 @@ public:
object = new GameObject();
// this will generate a new guid if the object is in an instance
- if (!object->LoadGameObjectFromDB(guidLow, map))
+ if (!object->LoadFromDB(guidLow, map, true))
{
delete object;
return false;
}
/// @todo is it really necessary to add both the real and DB table guid here ?
- sObjectMgr->AddGameobjectToGrid(guidLow, sObjectMgr->GetGOData(guidLow));
+ sObjectMgr->AddGameobjectToGrid(guidLow, sObjectMgr->GetGameObjectData(guidLow));
handler->PSendSysMessage(LANG_GAMEOBJECT_ADD, objectId, objectInfo->name.c_str(), guidLow, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ());
return true;
@@ -345,6 +351,9 @@ public:
if (!guidLow)
return false;
+ Player const* const player = handler->GetSession()->GetPlayer();
+ // force respawn to make sure we find something
+ player->GetMap()->RemoveRespawnTime(SPAWN_TYPE_GAMEOBJECT, guidLow, true);
GameObject* object = handler->GetObjectFromPlayerMapByDbGuid(guidLow);
if (!object)
{
@@ -356,7 +365,7 @@ public:
ObjectGuid ownerGuid = object->GetOwnerGUID();
if (ownerGuid)
{
- Unit* owner = ObjectAccessor::GetUnit(*handler->GetSession()->GetPlayer(), ownerGuid);
+ Unit* owner = ObjectAccessor::GetUnit(*player, ownerGuid);
if (!owner || !ownerGuid.IsPlayer())
{
handler->PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, ownerGuid.GetCounter(), guidLow);
@@ -430,7 +439,7 @@ public:
object->Delete();
object = new GameObject();
- if (!object->LoadGameObjectFromDB(guidLow, map))
+ if (!object->LoadFromDB(guidLow, map, true))
{
delete object;
return false;
@@ -499,7 +508,7 @@ public:
object->Delete();
object = new GameObject();
- if (!object->LoadGameObjectFromDB(guidLow, map))
+ if (!object->LoadFromDB(guidLow, map, true))
{
delete object;
return false;
@@ -578,7 +587,7 @@ public:
if (!gameObjectInfo)
continue;
- handler->PSendSysMessage(LANG_GO_LIST_CHAT, guid, entry, guid, gameObjectInfo->name.c_str(), x, y, z, mapId);
+ handler->PSendSysMessage(LANG_GO_LIST_CHAT, guid, entry, guid, gameObjectInfo->name.c_str(), x, y, z, mapId, "", "");
++count;
} while (result->NextRow());
@@ -611,7 +620,7 @@ public:
if (!cValue)
return false;
ObjectGuid::LowType guidLow = atoul(cValue);
- GameObjectData const* data = sObjectMgr->GetGOData(guidLow);
+ GameObjectData const* data = sObjectMgr->GetGameObjectData(guidLow);
if (!data)
return false;
entry = data->id;
@@ -623,9 +632,16 @@ public:
GameObjectTemplate const* gameObjectInfo = sObjectMgr->GetGameObjectTemplate(entry);
+ GameObject* thisGO = nullptr;
+
if (!gameObjectInfo)
return false;
+ if (*args && handler->GetSession()->GetPlayer())
+ thisGO = handler->GetSession()->GetPlayer()->FindNearestGameObject(entry, 30);
+ else if (handler->getSelectedObject() && handler->getSelectedObject()->GetTypeId() == TYPEID_GAMEOBJECT)
+ thisGO = handler->getSelectedObject()->ToGameObject();
+
type = gameObjectInfo->type;
displayId = gameObjectInfo->displayId;
name = gameObjectInfo->name;
@@ -634,10 +650,32 @@ public:
else if (type == GAMEOBJECT_TYPE_FISHINGHOLE)
lootId = gameObjectInfo->fishinghole.lootId;
+ // If we have a real object, send some info about it
+ if (thisGO)
+ {
+ handler->PSendSysMessage(LANG_SPAWNINFO_GUIDINFO, thisGO->GetGUID().ToString().c_str());
+ handler->PSendSysMessage(LANG_SPAWNINFO_SPAWNID_LOCATION, thisGO->GetSpawnId(), thisGO->GetPositionX(), thisGO->GetPositionY(), thisGO->GetPositionZ());
+ if (Player* player = handler->GetSession()->GetPlayer())
+ {
+ Position playerPos = player->GetPosition();
+ float dist = thisGO->GetExactDist(&playerPos);
+ handler->PSendSysMessage(LANG_SPAWNINFO_DISTANCEFROMPLAYER, dist);
+ }
+ }
handler->PSendSysMessage(LANG_GOINFO_ENTRY, entry);
handler->PSendSysMessage(LANG_GOINFO_TYPE, type);
handler->PSendSysMessage(LANG_GOINFO_LOOTID, lootId);
handler->PSendSysMessage(LANG_GOINFO_DISPLAYID, displayId);
+ if (WorldObject* object = handler->getSelectedObject())
+ {
+ if (object->ToGameObject() && object->ToGameObject()->GetGameObjectData() && object->ToGameObject()->GetGameObjectData()->spawnGroupData->groupId)
+ {
+ SpawnGroupTemplateData const* groupData = object->ToGameObject()->GetGameObjectData()->spawnGroupData;
+ handler->PSendSysMessage(LANG_SPAWNINFO_GROUP_ID, groupData->name.c_str(), groupData->groupId, groupData->flags, object->GetMap()->IsSpawnGroupActive(groupData->groupId));
+ }
+ if (object->ToGameObject())
+ handler->PSendSysMessage(LANG_SPAWNINFO_COMPATIBILITY_MODE, object->ToGameObject()->GetRespawnCompatibilityMode());
+ }
handler->PSendSysMessage(LANG_GOINFO_NAME, name.c_str());
handler->PSendSysMessage(LANG_GOINFO_SIZE, gameObjectInfo->size);
diff --git a/src/server/scripts/Commands/cs_instance.cpp b/src/server/scripts/Commands/cs_instance.cpp
index 682976ba897..6855fe21efc 100644
--- a/src/server/scripts/Commands/cs_instance.cpp
+++ b/src/server/scripts/Commands/cs_instance.cpp
@@ -256,8 +256,7 @@ public:
}
map->GetInstanceScript()->SetBossState(encounterId, EncounterState(state));
- std::string stateName = InstanceScript::GetBossStateName(state);
- handler->PSendSysMessage(LANG_COMMAND_INST_SET_BOSS_STATE, encounterId, state, stateName);
+ handler->PSendSysMessage(LANG_COMMAND_INST_SET_BOSS_STATE, encounterId, state, InstanceScript::GetBossStateName(state));
return true;
}
@@ -321,8 +320,7 @@ public:
}
uint32 state = map->GetInstanceScript()->GetBossState(encounterId);
- std::string stateName = InstanceScript::GetBossStateName(state);
- handler->PSendSysMessage(LANG_COMMAND_INST_GET_BOSS_STATE, encounterId, state, stateName);
+ handler->PSendSysMessage(LANG_COMMAND_INST_GET_BOSS_STATE, encounterId, state, InstanceScript::GetBossStateName(state));
return true;
}
};
diff --git a/src/server/scripts/Commands/cs_list.cpp b/src/server/scripts/Commands/cs_list.cpp
index 8b502f60e11..304b7578177 100644
--- a/src/server/scripts/Commands/cs_list.cpp
+++ b/src/server/scripts/Commands/cs_list.cpp
@@ -25,9 +25,12 @@ EndScriptData */
#include "ScriptMgr.h"
#include "CharacterCache.h"
#include "Chat.h"
+#include "Creature.h"
#include "DatabaseEnv.h"
#include "DBCStores.h"
+#include "GameObject.h"
#include "Language.h"
+#include "MapManager.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Player.h"
@@ -45,11 +48,13 @@ public:
{
static std::vector<ChatCommand> listCommandTable =
{
- { "creature", rbac::RBAC_PERM_COMMAND_LIST_CREATURE, true, &HandleListCreatureCommand, "" },
- { "item", rbac::RBAC_PERM_COMMAND_LIST_ITEM, true, &HandleListItemCommand, "" },
- { "object", rbac::RBAC_PERM_COMMAND_LIST_OBJECT, true, &HandleListObjectCommand, "" },
- { "auras", rbac::RBAC_PERM_COMMAND_LIST_AURAS, false, &HandleListAurasCommand, "" },
- { "mail", rbac::RBAC_PERM_COMMAND_LIST_MAIL, true, &HandleListMailCommand, "" },
+ { "creature", rbac::RBAC_PERM_COMMAND_LIST_CREATURE, true, &HandleListCreatureCommand, "" },
+ { "item", rbac::RBAC_PERM_COMMAND_LIST_ITEM, true, &HandleListItemCommand, "" },
+ { "object", rbac::RBAC_PERM_COMMAND_LIST_OBJECT, true, &HandleListObjectCommand, "" },
+ { "auras", rbac::RBAC_PERM_COMMAND_LIST_AURAS, false, &HandleListAurasCommand, "" },
+ { "mail", rbac::RBAC_PERM_COMMAND_LIST_MAIL, true, &HandleListMailCommand, "" },
+ { "spawnpoints", rbac::RBAC_PERM_COMMAND_LIST_SPAWNPOINTS, false, &HandleListSpawnPointsCommand, "" },
+ { "respawns", rbac::RBAC_PERM_COMMAND_LIST_RESPAWNS, false, &HandleListRespawnsCommand, "" },
};
static std::vector<ChatCommand> commandTable =
{
@@ -117,11 +122,40 @@ public:
float y = fields[2].GetFloat();
float z = fields[3].GetFloat();
uint16 mapId = fields[4].GetUInt16();
+ bool liveFound = false;
+ // Get map (only support base map from console)
+ Map* thisMap;
if (handler->GetSession())
- handler->PSendSysMessage(LANG_CREATURE_LIST_CHAT, guid, guid, cInfo->Name.c_str(), x, y, z, mapId);
+ thisMap = handler->GetSession()->GetPlayer()->GetMap();
else
- handler->PSendSysMessage(LANG_CREATURE_LIST_CONSOLE, guid, cInfo->Name.c_str(), x, y, z, mapId);
+ thisMap = sMapMgr->FindBaseNonInstanceMap(mapId);
+
+ // If map found, try to find active version of this creature
+ if (thisMap)
+ {
+ auto const creBounds = thisMap->GetCreatureBySpawnIdStore().equal_range(guid);
+ if (creBounds.first != creBounds.second)
+ {
+ for (std::unordered_multimap<uint32, Creature*>::const_iterator itr = creBounds.first; itr != creBounds.second;)
+ {
+ if (handler->GetSession())
+ handler->PSendSysMessage(LANG_CREATURE_LIST_CHAT, guid, guid, cInfo->Name.c_str(), x, y, z, mapId, itr->second->GetGUID().ToString().c_str(), itr->second->IsAlive() ? "*" : " ");
+ else
+ handler->PSendSysMessage(LANG_CREATURE_LIST_CONSOLE, guid, cInfo->Name.c_str(), x, y, z, mapId, itr->second->GetGUID().ToString().c_str(), itr->second->IsAlive() ? "*" : " ");
+ ++itr;
+ }
+ liveFound = true;
+ }
+ }
+
+ if (!liveFound)
+ {
+ if (handler->GetSession())
+ handler->PSendSysMessage(LANG_CREATURE_LIST_CHAT, guid, guid, cInfo->Name.c_str(), x, y, z, mapId, "", "");
+ else
+ handler->PSendSysMessage(LANG_CREATURE_LIST_CONSOLE, guid, cInfo->Name.c_str(), x, y, z, mapId, "", "");
+ }
}
while (result->NextRow());
}
@@ -407,11 +441,40 @@ public:
float z = fields[3].GetFloat();
uint16 mapId = fields[4].GetUInt16();
uint32 entry = fields[5].GetUInt32();
+ bool liveFound = false;
+ // Get map (only support base map from console)
+ Map* thisMap;
if (handler->GetSession())
- handler->PSendSysMessage(LANG_GO_LIST_CHAT, guid, entry, guid, gInfo->name.c_str(), x, y, z, mapId);
+ thisMap = handler->GetSession()->GetPlayer()->GetMap();
else
- handler->PSendSysMessage(LANG_GO_LIST_CONSOLE, guid, gInfo->name.c_str(), x, y, z, mapId);
+ thisMap = sMapMgr->FindBaseNonInstanceMap(mapId);
+
+ // If map found, try to find active version of this object
+ if (thisMap)
+ {
+ auto const goBounds = thisMap->GetGameObjectBySpawnIdStore().equal_range(guid);
+ if (goBounds.first != goBounds.second)
+ {
+ for (std::unordered_multimap<uint32, GameObject*>::const_iterator itr = goBounds.first; itr != goBounds.second;)
+ {
+ if (handler->GetSession())
+ handler->PSendSysMessage(LANG_GO_LIST_CHAT, guid, entry, guid, gInfo->name.c_str(), x, y, z, mapId, itr->second->GetGUID().ToString().c_str(), itr->second->isSpawned() ? "*" : " ");
+ else
+ handler->PSendSysMessage(LANG_GO_LIST_CONSOLE, guid, gInfo->name.c_str(), x, y, z, mapId, itr->second->GetGUID().ToString().c_str(), itr->second->isSpawned() ? "*" : " ");
+ ++itr;
+ }
+ liveFound = true;
+ }
+ }
+
+ if (!liveFound)
+ {
+ if (handler->GetSession())
+ handler->PSendSysMessage(LANG_GO_LIST_CHAT, guid, entry, guid, gInfo->name.c_str(), x, y, z, mapId, "", "");
+ else
+ handler->PSendSysMessage(LANG_GO_LIST_CONSOLE, guid, gInfo->name.c_str(), x, y, z, mapId, "", "");
+ }
}
while (result->NextRow());
}
@@ -581,8 +644,104 @@ public:
handler->PSendSysMessage(LANG_LIST_MAIL_NOT_FOUND);
return true;
}
+
+ static bool HandleListSpawnPointsCommand(ChatHandler* handler, char const* /*args*/)
+ {
+ Player const* player = handler->GetSession()->GetPlayer();
+ Map const* map = player->GetMap();
+ uint32 const mapId = map->GetId();
+ bool const showAll = map->IsBattlegroundOrArena() || map->IsDungeon();
+ handler->PSendSysMessage("Listing all spawn points in map %u (%s)%s:", mapId, map->GetMapName(), showAll ? "" : " within 5000yd");
+ for (auto const& pair : sObjectMgr->GetAllCreatureData())
+ {
+ SpawnData const& data = pair.second;
+ if (data.spawnPoint.GetMapId() != mapId)
+ continue;
+ CreatureTemplate const* cTemp = sObjectMgr->GetCreatureTemplate(data.id);
+ if (!cTemp)
+ continue;
+ if (showAll || data.spawnPoint.IsInDist2d(player, 5000.0))
+ handler->PSendSysMessage("Type: %u | SpawnId: %u | Entry: %u (%s) | X: %.3f | Y: %.3f | Z: %.3f", uint32(data.type), data.spawnId, data.id, cTemp->Name.c_str(), data.spawnPoint.GetPositionX(), data.spawnPoint.GetPositionY(), data.spawnPoint.GetPositionZ());
+ }
+ for (auto const& pair : sObjectMgr->GetAllGameObjectData())
+ {
+ SpawnData const& data = pair.second;
+ if (data.spawnPoint.GetMapId() != mapId)
+ continue;
+ GameObjectTemplate const* goTemp = sObjectMgr->GetGameObjectTemplate(data.id);
+ if (!goTemp)
+ continue;
+ if (showAll || data.spawnPoint.IsInDist2d(player, 5000.0))
+ handler->PSendSysMessage("Type: %u | SpawnId: %u | Entry: %u (%s) | X: %.3f | Y: %.3f | Z: %.3f", uint32(data.type), data.spawnId, data.id, goTemp->name.c_str(), data.spawnPoint.GetPositionX(), data.spawnPoint.GetPositionY(), data.spawnPoint.GetPositionZ());
+ }
+ return true;
+ }
+
+ static char const* GetZoneName(uint32 zoneId, LocaleConstant locale)
+ {
+ AreaTableEntry const* zoneEntry = sAreaTableStore.LookupEntry(zoneId);
+ return zoneEntry ? zoneEntry->area_name[locale] : "<unknown zone>";
+ }
+ static bool HandleListRespawnsCommand(ChatHandler* handler, char const* args)
+ {
+ Player const* player = handler->GetSession()->GetPlayer();
+ Map const* map = player->GetMap();
+ uint32 range = 0;
+ if (*args)
+ range = atoi((char*)args);
+
+ RespawnVector respawns;
+ LocaleConstant locale = handler->GetSession()->GetSessionDbcLocale();
+ char const* stringOverdue = sObjectMgr->GetTrinityString(LANG_LIST_RESPAWNS_OVERDUE, locale);
+ char const* stringCreature = sObjectMgr->GetTrinityString(LANG_LIST_RESPAWNS_CREATURES, locale);
+ char const* stringGameobject = sObjectMgr->GetTrinityString(LANG_LIST_RESPAWNS_GAMEOBJECTS, locale);
+
+ uint32 zoneId = player->GetZoneId();
+ if (range)
+ handler->PSendSysMessage(LANG_LIST_RESPAWNS_RANGE, stringCreature, range);
+ else
+ handler->PSendSysMessage(LANG_LIST_RESPAWNS_ZONE, stringCreature, GetZoneName(zoneId, handler->GetSessionDbcLocale()), zoneId);
+ handler->PSendSysMessage(LANG_LIST_RESPAWNS_LISTHEADER);
+ map->GetRespawnInfo(respawns, SPAWN_TYPEMASK_CREATURE, range ? 0 : zoneId);
+ for (RespawnInfo* ri : respawns)
+ {
+ CreatureData const* data = sObjectMgr->GetCreatureData(ri->spawnId);
+ if (!data)
+ continue;
+ if (range && !player->IsInDist(data->spawnPoint, range))
+ continue;
+ uint32 gridY = ri->gridId / MAX_NUMBER_OF_GRIDS;
+ uint32 gridX = ri->gridId % MAX_NUMBER_OF_GRIDS;
+
+ std::string respawnTime = ri->respawnTime > time(NULL) ? secsToTimeString(uint64(ri->respawnTime - time(NULL)), true) : stringOverdue;
+ handler->PSendSysMessage("%u | %u | [%02u,%02u] | %s (%u) | %s", ri->spawnId, ri->entry, gridX, gridY, GetZoneName(ri->zoneId, handler->GetSessionDbcLocale()), ri->zoneId, map->IsSpawnGroupActive(data->spawnGroupData->groupId) ? respawnTime.c_str() : "inactive");
+ }
+
+ respawns.clear();
+ if (range)
+ handler->PSendSysMessage(LANG_LIST_RESPAWNS_RANGE, stringGameobject, range);
+ else
+ handler->PSendSysMessage(LANG_LIST_RESPAWNS_ZONE, stringGameobject, GetZoneName(zoneId, handler->GetSessionDbcLocale()), zoneId);
+ handler->PSendSysMessage(LANG_LIST_RESPAWNS_LISTHEADER);
+ map->GetRespawnInfo(respawns, SPAWN_TYPEMASK_GAMEOBJECT, range ? 0 : zoneId);
+ for (RespawnInfo* ri : respawns)
+ {
+ GameObjectData const* data = sObjectMgr->GetGameObjectData(ri->spawnId);
+ if (!data)
+ continue;
+ if (range && !player->IsInDist(data->spawnPoint, range))
+ continue;
+ uint32 gridY = ri->gridId / MAX_NUMBER_OF_GRIDS;
+ uint32 gridX = ri->gridId % MAX_NUMBER_OF_GRIDS;
+
+ std::string respawnTime = ri->respawnTime > time(NULL) ? secsToTimeString(uint64(ri->respawnTime - time(NULL)), true) : stringOverdue;
+ handler->PSendSysMessage("%u | %u | [% 02u, % 02u] | %s (%u) | %s", ri->spawnId, ri->entry, gridX, gridY, GetZoneName(ri->zoneId, handler->GetSessionDbcLocale()), ri->zoneId, map->IsSpawnGroupActive(data->spawnGroupData->groupId) ? respawnTime.c_str() : "inactive");
+ }
+ return true;
+ }
};
+
void AddSC_list_commandscript()
{
new list_commandscript();
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index 29f1a0763fb..0860585dc65 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -544,10 +544,11 @@ public:
}
else if (map->Instanceable())
{
- Group* targetGroup = target->GetGroup();
Map* targetMap = target->GetMap();
- Player* targetGroupLeader = ObjectAccessor::GetPlayer(map, targetGroup->GetLeaderGUID());
-
+ Player* targetGroupLeader = nullptr;
+ if (Group* targetGroup = target->GetGroup())
+ targetGroupLeader = ObjectAccessor::GetPlayer(map, targetGroup->GetLeaderGUID());
+
// check if far teleport is allowed
if (!targetGroupLeader || (targetGroupLeader->GetMapId() != map->GetId()) || (targetGroupLeader->GetInstanceId() != map->GetInstanceId()))
if ((targetMap->GetId() != map->GetId()) || (targetMap->GetInstanceId() != map->GetInstanceId()))
@@ -1910,10 +1911,22 @@ public:
return true;
}
+ // First handle any creatures that still have a corpse around
Trinity::RespawnDo u_do;
Trinity::WorldObjectWorker<Trinity::RespawnDo> worker(player, u_do);
Cell::VisitGridObjects(player, worker, player->GetGridActivationRange());
+ // Now handle any that had despawned, but had respawn time logged.
+ RespawnVector data;
+ player->GetMap()->GetRespawnInfo(data, SPAWN_TYPEMASK_ALL, 0);
+ if (!data.empty())
+ {
+ uint32 const gridId = Trinity::ComputeGridCoord(player->GetPositionX(), player->GetPositionY()).GetId();
+ for (RespawnInfo* info : data)
+ if (info->gridId == gridId)
+ player->GetMap()->RemoveRespawnTime(info, true);
+ }
+
return true;
}
@@ -1977,15 +1990,15 @@ public:
stmt->setInt64(0, muteTime);
}
- stmt->setString(1, muteReasonStr.c_str());
- stmt->setString(2, muteBy.c_str());
+ stmt->setString(1, muteReasonStr);
+ stmt->setString(2, muteBy);
stmt->setUInt32(3, accountId);
LoginDatabase.Execute(stmt);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT_MUTE);
stmt->setUInt32(0, accountId);
stmt->setUInt32(1, notSpeakTime);
- stmt->setString(2, muteBy.c_str());
- stmt->setString(3, muteReasonStr.c_str());
+ stmt->setString(2, muteBy);
+ stmt->setString(3, muteReasonStr);
LoginDatabase.Execute(stmt);
std::string nameLink = handler->playerLink(targetName);
@@ -2122,9 +2135,9 @@ public:
float x, y, z;
motionMaster->GetDestination(x, y, z);
- for (uint8 i = 0; i < MAX_MOTION_SLOT; ++i)
+ for (uint8 itr = 0; itr < MAX_MOTION_SLOT; ++itr)
{
- MovementGenerator* movementGenerator = motionMaster->GetMotionSlot(i);
+ MovementGenerator* movementGenerator = motionMaster->GetMotionSlot(MovementSlot(itr));
if (!movementGenerator)
{
handler->SendSysMessage("Empty");
diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp
index dfb9ddb66a6..54c48cd1205 100644
--- a/src/server/scripts/Commands/cs_npc.cpp
+++ b/src/server/scripts/Commands/cs_npc.cpp
@@ -176,6 +176,86 @@ EnumName<CreatureFlagsExtra> const flagsExtra[FLAGS_EXTRA_COUNT] =
CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK)
};
+bool HandleNpcSpawnGroup(ChatHandler* handler, char const* args)
+{
+ if (!*args)
+ return false;
+
+ bool ignoreRespawn = false;
+ bool force = false;
+ uint32 groupId = 0;
+
+ // Decode arguments
+ char* arg = strtok((char*)args, " ");
+ while (arg)
+ {
+ std::string thisArg = arg;
+ std::transform(thisArg.begin(), thisArg.end(), thisArg.begin(), ::tolower);
+ if (thisArg == "ignorerespawn")
+ ignoreRespawn = true;
+ else if (thisArg == "force")
+ force = true;
+ else if (thisArg.empty() || !(std::count_if(thisArg.begin(), thisArg.end(), ::isdigit) == (int)thisArg.size()))
+ return false;
+ else
+ groupId = atoi(thisArg.c_str());
+
+ arg = strtok(NULL, " ");
+ }
+
+ Player* player = handler->GetSession()->GetPlayer();
+
+ std::vector <WorldObject*> creatureList;
+ if (!player->GetMap()->SpawnGroupSpawn(groupId, ignoreRespawn, force, &creatureList))
+ {
+ handler->PSendSysMessage(LANG_SPAWNGROUP_BADGROUP, groupId);
+ handler->SetSentErrorMessage(true);
+ return false;
+ }
+
+ handler->PSendSysMessage(LANG_SPAWNGROUP_SPAWNCOUNT, creatureList.size());
+ for (WorldObject* obj : creatureList)
+ handler->PSendSysMessage("%s (%s)", obj->GetName(), obj->GetGUID().ToString().c_str());
+
+ return true;
+}
+
+bool HandleNpcDespawnGroup(ChatHandler* handler, char const* args)
+{
+ if (!*args)
+ return false;
+
+ bool deleteRespawnTimes = false;
+ uint32 groupId = 0;
+
+ // Decode arguments
+ char* arg = strtok((char*)args, " ");
+ while (arg)
+ {
+ std::string thisArg = arg;
+ std::transform(thisArg.begin(), thisArg.end(), thisArg.begin(), ::tolower);
+ if (thisArg == "removerespawntime")
+ deleteRespawnTimes = true;
+ else if (thisArg.empty() || !(std::count_if(thisArg.begin(), thisArg.end(), ::isdigit) == (int)thisArg.size()))
+ return false;
+ else
+ groupId = atoi(thisArg.c_str());
+
+ arg = strtok(nullptr, " ");
+ }
+
+ Player* player = handler->GetSession()->GetPlayer();
+
+ if (!player->GetMap()->SpawnGroupDespawn(groupId, deleteRespawnTimes))
+ {
+ handler->PSendSysMessage(LANG_SPAWNGROUP_BADGROUP, groupId);
+ handler->SetSentErrorMessage(true);
+ return false;
+ }
+
+ return true;
+}
+
class npc_commandscript : public CommandScript
{
public:
@@ -219,21 +299,23 @@ public:
};
static std::vector<ChatCommand> npcCommandTable =
{
- { "info", rbac::RBAC_PERM_COMMAND_NPC_INFO, false, &HandleNpcInfoCommand, "" },
- { "near", rbac::RBAC_PERM_COMMAND_NPC_NEAR, false, &HandleNpcNearCommand, "" },
- { "move", rbac::RBAC_PERM_COMMAND_NPC_MOVE, false, &HandleNpcMoveCommand, "" },
- { "playemote", rbac::RBAC_PERM_COMMAND_NPC_PLAYEMOTE, false, &HandleNpcPlayEmoteCommand, "" },
- { "say", rbac::RBAC_PERM_COMMAND_NPC_SAY, false, &HandleNpcSayCommand, "" },
- { "textemote", rbac::RBAC_PERM_COMMAND_NPC_TEXTEMOTE, false, &HandleNpcTextEmoteCommand, "" },
- { "whisper", rbac::RBAC_PERM_COMMAND_NPC_WHISPER, false, &HandleNpcWhisperCommand, "" },
- { "yell", rbac::RBAC_PERM_COMMAND_NPC_YELL, false, &HandleNpcYellCommand, "" },
- { "tame", rbac::RBAC_PERM_COMMAND_NPC_TAME, false, &HandleNpcTameCommand, "" },
- { "add", rbac::RBAC_PERM_COMMAND_NPC_ADD, false, nullptr, "", npcAddCommandTable },
- { "delete", rbac::RBAC_PERM_COMMAND_NPC_DELETE, false, nullptr, "", npcDeleteCommandTable },
- { "follow", rbac::RBAC_PERM_COMMAND_NPC_FOLLOW, false, nullptr, "", npcFollowCommandTable },
- { "set", rbac::RBAC_PERM_COMMAND_NPC_SET, false, nullptr, "", npcSetCommandTable },
- { "evade", rbac::RBAC_PERM_COMMAND_NPC_EVADE, false, &HandleNpcEvadeCommand, "" },
- { "showloot", rbac::RBAC_PERM_COMMAND_NPC_SHOWLOOT, false, &HandleNpcShowLootCommand, "" },
+ { "info", rbac::RBAC_PERM_COMMAND_NPC_INFO, false, &HandleNpcInfoCommand, "" },
+ { "near", rbac::RBAC_PERM_COMMAND_NPC_NEAR, false, &HandleNpcNearCommand, "" },
+ { "move", rbac::RBAC_PERM_COMMAND_NPC_MOVE, false, &HandleNpcMoveCommand, "" },
+ { "playemote", rbac::RBAC_PERM_COMMAND_NPC_PLAYEMOTE, false, &HandleNpcPlayEmoteCommand, "" },
+ { "say", rbac::RBAC_PERM_COMMAND_NPC_SAY, false, &HandleNpcSayCommand, "" },
+ { "textemote", rbac::RBAC_PERM_COMMAND_NPC_TEXTEMOTE, false, &HandleNpcTextEmoteCommand, "" },
+ { "whisper", rbac::RBAC_PERM_COMMAND_NPC_WHISPER, false, &HandleNpcWhisperCommand, "" },
+ { "yell", rbac::RBAC_PERM_COMMAND_NPC_YELL, false, &HandleNpcYellCommand, "" },
+ { "tame", rbac::RBAC_PERM_COMMAND_NPC_TAME, false, &HandleNpcTameCommand, "" },
+ { "spawngroup", rbac::RBAC_PERM_COMMAND_NPC_SPAWNGROUP, false, &HandleNpcSpawnGroup, "" },
+ { "despawngroup", rbac::RBAC_PERM_COMMAND_NPC_DESPAWNGROUP, false, &HandleNpcDespawnGroup, "" },
+ { "add", rbac::RBAC_PERM_COMMAND_NPC_ADD, false, nullptr, "", npcAddCommandTable },
+ { "delete", rbac::RBAC_PERM_COMMAND_NPC_DELETE, false, nullptr, "", npcDeleteCommandTable },
+ { "follow", rbac::RBAC_PERM_COMMAND_NPC_FOLLOW, false, nullptr, "", npcFollowCommandTable },
+ { "set", rbac::RBAC_PERM_COMMAND_NPC_SET, false, nullptr, "", npcSetCommandTable },
+ { "evade", rbac::RBAC_PERM_COMMAND_NPC_EVADE, false, &HandleNpcEvadeCommand, "" },
+ { "showloot", rbac::RBAC_PERM_COMMAND_NPC_SHOWLOOT, false, &HandleNpcShowLootCommand, "" },
};
static std::vector<ChatCommand> commandTable =
{
@@ -257,22 +339,16 @@ public:
return false;
Player* chr = handler->GetSession()->GetPlayer();
- float x = chr->GetPositionX();
- float y = chr->GetPositionY();
- float z = chr->GetPositionZ();
- float o = chr->GetOrientation();
Map* map = chr->GetMap();
if (Transport* trans = chr->GetTransport())
{
ObjectGuid::LowType guid = map->GenerateLowGuid<HighGuid::Unit>();
CreatureData& data = sObjectMgr->NewOrExistCreatureData(guid);
+ data.spawnId = guid;
data.id = id;
data.phaseMask = chr->GetPhaseMaskForSpawn();
- data.posX = chr->GetTransOffsetX();
- data.posY = chr->GetTransOffsetY();
- data.posZ = chr->GetTransOffsetZ();
- data.orientation = chr->GetTransOffsetO();
+ data.spawnPoint.Relocate(chr->GetTransOffsetX(), chr->GetTransOffsetY(), chr->GetTransOffsetZ(), chr->GetTransOffsetO());
Creature* creature = trans->CreateNPCPassenger(guid, &data);
@@ -283,7 +359,7 @@ public:
}
Creature* creature = new Creature();
- if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), id, x, y, z, o))
+ if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), id, *chr))
{
delete creature;
return false;
@@ -298,7 +374,7 @@ public:
creature->CleanupsBeforeDelete();
delete creature;
creature = new Creature();
- if (!creature->LoadCreatureFromDB(db_guid, map))
+ if (!creature->LoadFromDB(db_guid, map, true, true))
{
delete creature;
return false;
@@ -473,7 +549,7 @@ public:
static bool HandleNpcDeleteCommand(ChatHandler* handler, char const* args)
{
- Creature* unit = nullptr;
+ Creature* creature = nullptr;
if (*args)
{
@@ -485,22 +561,30 @@ public:
ObjectGuid::LowType lowguid = atoul(cId);
if (!lowguid)
return false;
- unit = handler->GetCreatureFromPlayerMapByDbGuid(lowguid);
+ // force respawn to make sure we find something
+ handler->GetSession()->GetPlayer()->GetMap()->RemoveRespawnTime(SPAWN_TYPE_CREATURE, lowguid, true);
+ // then try to find it
+ creature = handler->GetCreatureFromPlayerMapByDbGuid(lowguid);
}
else
- unit = handler->getSelectedCreature();
+ creature = handler->getSelectedCreature();
- if (!unit || unit->IsPet() || unit->IsTotem())
+ if (!creature || creature->IsPet() || creature->IsTotem())
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
- // Delete the creature
- unit->CombatStop();
- unit->DeleteFromDB();
- unit->AddObjectToRemoveList();
+ if (TempSummon* summon = creature->ToTempSummon())
+ summon->UnSummon();
+ else
+ {
+ // Delete the creature
+ creature->CombatStop();
+ creature->DeleteFromDB();
+ creature->AddObjectToRemoveList();
+ }
handler->SendSysMessage(LANG_COMMAND_DELCREATMESSAGE);
@@ -690,13 +774,20 @@ public:
uint32 nativeid = target->GetNativeDisplayId();
uint32 Entry = target->GetEntry();
- int64 curRespawnDelay = target->GetRespawnTimeEx()-time(nullptr);
+ int64 curRespawnDelay = target->GetRespawnCompatibilityMode() ? target->GetRespawnTimeEx() - time(nullptr) : target->GetMap()->GetCreatureRespawnTime(target->GetSpawnId()) - time(nullptr);
+
if (curRespawnDelay < 0)
curRespawnDelay = 0;
std::string curRespawnDelayStr = secsToTimeString(uint64(curRespawnDelay), true);
std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(), true);
handler->PSendSysMessage(LANG_NPCINFO_CHAR, target->GetSpawnId(), target->GetGUID().GetCounter(), faction, npcflags, Entry, displayid, nativeid);
+ if (target->GetCreatureData() && target->GetCreatureData()->spawnGroupData->groupId)
+ {
+ SpawnGroupTemplateData const* const groupData = target->GetCreatureData()->spawnGroupData;
+ handler->PSendSysMessage(LANG_SPAWNINFO_GROUP_ID, groupData->name.c_str(), groupData->groupId, groupData->flags, target->GetMap()->IsSpawnGroupActive(groupData->groupId));
+ }
+ handler->PSendSysMessage(LANG_SPAWNINFO_COMPATIBILITY_MODE, target->GetRespawnCompatibilityMode());
handler->PSendSysMessage(LANG_NPCINFO_LEVEL, target->getLevel());
handler->PSendSysMessage(LANG_NPCINFO_EQUIPMENT, target->GetCurrentEquipmentId(), target->GetOriginalEquipmentId());
handler->PSendSysMessage(LANG_NPCINFO_HEALTH, target->GetCreateHealth(), target->GetMaxHealth(), target->GetHealth());
@@ -766,7 +857,7 @@ public:
if (!creatureTemplate)
continue;
- handler->PSendSysMessage(LANG_CREATURE_LIST_CHAT, guid, guid, creatureTemplate->Name.c_str(), x, y, z, mapId);
+ handler->PSendSysMessage(LANG_CREATURE_LIST_CHAT, guid, guid, creatureTemplate->Name.c_str(), x, y, z, mapId, "", "");
++count;
}
@@ -784,8 +875,13 @@ public:
ObjectGuid::LowType lowguid = 0;
Creature* creature = handler->getSelectedCreature();
+ Player const* player = handler->GetSession()->GetPlayer();
+ if (!player)
+ return false;
- if (!creature)
+ if (creature)
+ lowguid = creature->GetSpawnId();
+ else
{
// number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
char* cId = handler->extractKeyFromLink((char*)args, "Hcreature");
@@ -793,63 +889,45 @@ public:
return false;
lowguid = atoul(cId);
-
- // Attempting creature load from DB data
- CreatureData const* data = sObjectMgr->GetCreatureData(lowguid);
- if (!data)
- {
- handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
- handler->SetSentErrorMessage(true);
- return false;
- }
-
- uint32 map_id = data->mapid;
-
- if (handler->GetSession()->GetPlayer()->GetMapId() != map_id)
- {
- handler->PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
- handler->SetSentErrorMessage(true);
- return false;
- }
}
- else
+ // Attempting creature load from DB data
+ CreatureData const* data = sObjectMgr->GetCreatureData(lowguid);
+ if (!data)
{
- lowguid = creature->GetSpawnId();
+ handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
+ handler->SetSentErrorMessage(true);
+ return false;
}
- float x = handler->GetSession()->GetPlayer()->GetPositionX();
- float y = handler->GetSession()->GetPlayer()->GetPositionY();
- float z = handler->GetSession()->GetPlayer()->GetPositionZ();
- float o = handler->GetSession()->GetPlayer()->GetOrientation();
-
- if (creature)
+ if (player->GetMapId() != data->spawnPoint.GetMapId())
{
- if (CreatureData const* data = sObjectMgr->GetCreatureData(creature->GetSpawnId()))
- {
- const_cast<CreatureData*>(data)->posX = x;
- const_cast<CreatureData*>(data)->posY = y;
- const_cast<CreatureData*>(data)->posZ = z;
- const_cast<CreatureData*>(data)->orientation = o;
- }
- creature->UpdatePosition(x, y, z, o);
- creature->GetMotionMaster()->Initialize();
- if (creature->IsAlive()) // dead creature will reset movement generator at respawn
- {
- creature->setDeathState(JUST_DIED);
- creature->Respawn();
- }
+ handler->PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
+ handler->SetSentErrorMessage(true);
+ return false;
}
- PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_POSITION);
+ // update position in memory
+ const_cast<CreatureData*>(data)->spawnPoint.Relocate(*player);
- stmt->setFloat(0, x);
- stmt->setFloat(1, y);
- stmt->setFloat(2, z);
- stmt->setFloat(3, o);
+ // update position in DB
+ PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_POSITION);
+ stmt->setFloat(0, player->GetPositionX());
+ stmt->setFloat(1, player->GetPositionY());
+ stmt->setFloat(2, player->GetPositionZ());
+ stmt->setFloat(3, player->GetOrientation());
stmt->setUInt32(4, lowguid);
-
WorldDatabase.Execute(stmt);
+ // respawn selected creature at the new location
+ if (creature)
+ {
+ if (creature->IsAlive())
+ creature->setDeathState(JUST_DIED);
+ creature->Respawn(true);
+ if (!creature->GetRespawnCompatibilityMode())
+ creature->AddObjectToRemoveList();
+ }
+
handler->PSendSysMessage(LANG_COMMAND_CREATUREMOVED);
return true;
}
@@ -1529,13 +1607,13 @@ public:
handler->PSendSysMessage(LANG_COMMAND_NPC_SHOWLOOT_LABEL_2, "Per-player quest items");
_IterateNotNormalLootMap(handler, loot.GetPlayerQuestItems(), loot.quest_items);
}
-
+
if (!loot.GetPlayerFFAItems().empty())
{
handler->PSendSysMessage(LANG_COMMAND_NPC_SHOWLOOT_LABEL_2, "FFA items per allowed player");
_IterateNotNormalLootMap(handler, loot.GetPlayerFFAItems(), loot.items);
}
-
+
if (!loot.GetPlayerNonQuestNonFFAConditionalItems().empty())
{
handler->PSendSysMessage(LANG_COMMAND_NPC_SHOWLOOT_LABEL_2, "Per-player conditional items");
diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp
index faeb77cccec..d40d67fc859 100644
--- a/src/server/scripts/Commands/cs_reload.cpp
+++ b/src/server/scripts/Commands/cs_reload.cpp
@@ -129,6 +129,8 @@ public:
{ "pickpocketing_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_PICKPOCKETING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesPickpocketingCommand, "" },
{ "points_of_interest", rbac::RBAC_PERM_COMMAND_RELOAD_POINTS_OF_INTEREST, true, &HandleReloadPointsOfInterestCommand, "" },
{ "prospecting_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_PROSPECTING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesProspectingCommand, "" },
+ { "quest_greeting", rbac::RBAC_PERM_COMMAND_RELOAD_QUEST_GREETING, true, &HandleReloadQuestGreetingCommand, "" },
+ { "quest_greeting_locale", rbac::RBAC_PERM_COMMAND_RELOAD_QUEST_GREETING_LOCALE, true, &HandleReloadLocalesQuestGreetingCommand, "" },
{ "quest_poi", rbac::RBAC_PERM_COMMAND_RELOAD_QUEST_POI, true, &HandleReloadQuestPOICommand, "" },
{ "quest_template", rbac::RBAC_PERM_COMMAND_RELOAD_QUEST_TEMPLATE, true, &HandleReloadQuestTemplateCommand, "" },
{ "rbac", rbac::RBAC_PERM_COMMAND_RELOAD_RBAC, true, &HandleReloadRBACCommand, "" },
@@ -243,6 +245,7 @@ public:
static bool HandleReloadAllQuestCommand(ChatHandler* handler, char const* /*args*/)
{
+ HandleReloadQuestGreetingCommand(handler, "");
HandleReloadQuestAreaTriggersCommand(handler, "a");
HandleReloadQuestPOICommand(handler, "a");
HandleReloadQuestTemplateCommand(handler, "a");
@@ -317,6 +320,7 @@ public:
HandleReloadLocalesPageTextCommand(handler, "a");
HandleReloadLocalesPointsOfInterestCommand(handler, "a");
HandleReloadLocalesQuestCommand(handler, "a");
+ HandleReloadLocalesQuestGreetingCommand(handler, "");
return true;
}
@@ -523,6 +527,22 @@ public:
return true;
}
+ static bool HandleReloadQuestGreetingCommand(ChatHandler* handler, char const* /*args*/)
+ {
+ TC_LOG_INFO("misc", "Re-Loading Quest Greeting ...");
+ sObjectMgr->LoadQuestGreetings();
+ handler->SendGlobalGMSysMessage("DB table `quest_greeting` reloaded.");
+ return true;
+ }
+
+ static bool HandleReloadLocalesQuestGreetingCommand(ChatHandler* handler, char const* /*args*/)
+ {
+ TC_LOG_INFO("misc", "Re-Loading Quest Greeting locales...");
+ sObjectMgr->LoadQuestGreetingsLocales();
+ handler->SendGlobalGMSysMessage("DB table `quest_greeting_locale` reloaded.");
+ return true;
+ }
+
static bool HandleReloadQuestTemplateCommand(ChatHandler* handler, char const* /*args*/)
{
TC_LOG_INFO("misc", "Re-Loading Quest Templates...");
diff --git a/src/server/scripts/Commands/cs_wp.cpp b/src/server/scripts/Commands/cs_wp.cpp
index efd02314d0e..582cc7b8c79 100644
--- a/src/server/scripts/Commands/cs_wp.cpp
+++ b/src/server/scripts/Commands/cs_wp.cpp
@@ -31,6 +31,7 @@ EndScriptData */
#include "MotionMaster.h"
#include "Player.h"
#include "RBAC.h"
+#include "WaypointDefines.h"
#include "WaypointManager.h"
#include "WorldSession.h"
@@ -259,7 +260,7 @@ public:
stmt->setUInt32(0, guildLow);
WorldDatabase.Execute(stmt);
- target->UpdateWaypointID(0);
+ target->UpdateCurrentWaypointInfo(0, 0);
stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_MOVEMENT_TYPE);
stmt->setUInt8(0, uint8(IDLE_MOTION_TYPE));
@@ -662,7 +663,7 @@ public:
// re-create
Creature* wpCreature = new Creature();
- if (!wpCreature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation()))
+ if (!wpCreature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, *chr))
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
delete wpCreature;
@@ -671,8 +672,7 @@ public:
wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
// To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
- /// @todo Should we first use "Create" then use "LoadFromDB"?
- if (!wpCreature->LoadCreatureFromDB(wpCreature->GetSpawnId(), map))
+ if (!wpCreature->LoadFromDB(wpCreature->GetSpawnId(), map, true, true))
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
delete wpCreature;
@@ -874,7 +874,7 @@ public:
float o = chr->GetOrientation();
Creature* wpCreature = new Creature();
- if (!wpCreature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), id, x, y, z, o))
+ if (!wpCreature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), id, { x, y, z, o }))
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
delete wpCreature;
@@ -891,7 +891,7 @@ public:
WorldDatabase.Execute(stmt);
// To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
- if (!wpCreature->LoadCreatureFromDB(wpCreature->GetSpawnId(), map))
+ if (!wpCreature->LoadFromDB(wpCreature->GetSpawnId(), map, true, true))
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
delete wpCreature;
@@ -937,7 +937,7 @@ public:
Map* map = chr->GetMap();
Creature* creature = new Creature();
- if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), id, x, y, z, o))
+ if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), id, { x, y, z, o }))
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
delete creature;
@@ -945,7 +945,7 @@ public:
}
creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
- if (!creature->LoadCreatureFromDB(creature->GetSpawnId(), map))
+ if (!creature->LoadFromDB(creature->GetSpawnId(), map, true, true))
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
delete creature;
@@ -986,7 +986,7 @@ public:
Map* map = chr->GetMap();
Creature* creature = new Creature();
- if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), id, x, y, z, o))
+ if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), id, { x, y, z, o }))
{
handler->PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id);
delete creature;
@@ -994,7 +994,7 @@ public:
}
creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
- if (!creature->LoadCreatureFromDB(creature->GetSpawnId(), map))
+ if (!creature->LoadFromDB(creature->GetSpawnId(), map, true, true))
{
handler->PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id);
delete creature;
diff --git a/src/server/scripts/EasternKingdoms/AlteracValley/alterac_valley.cpp b/src/server/scripts/EasternKingdoms/AlteracValley/alterac_valley.cpp
index f0edc7af0c7..b58fc0b8d8e 100644
--- a/src/server/scripts/EasternKingdoms/AlteracValley/alterac_valley.cpp
+++ b/src/server/scripts/EasternKingdoms/AlteracValley/alterac_valley.cpp
@@ -107,7 +107,7 @@ class npc_av_marshal_or_warmaster : public CreatureScript
events.ScheduleEvent(EVENT_CHECK_RESET, 5000);
}
- void JustRespawned() override
+ void JustAppeared() override
{
Reset();
}
diff --git a/src/server/scripts/EasternKingdoms/AlteracValley/boss_drekthar.cpp b/src/server/scripts/EasternKingdoms/AlteracValley/boss_drekthar.cpp
index cf034ed0ece..ed97d7670a1 100644
--- a/src/server/scripts/EasternKingdoms/AlteracValley/boss_drekthar.cpp
+++ b/src/server/scripts/EasternKingdoms/AlteracValley/boss_drekthar.cpp
@@ -71,7 +71,7 @@ public:
events.ScheduleEvent(EVENT_RANDOM_YELL, urand(20 * IN_MILLISECONDS, 30 * IN_MILLISECONDS)); //20 to 30 seconds
}
- void JustRespawned() override
+ void JustAppeared() override
{
Reset();
Talk(SAY_RESPAWN);
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp
index bcd4a915595..854f571c18c 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp
@@ -135,9 +135,9 @@ public:
return GetBlackrockDepthsAI<npc_grimstoneAI>(creature);
}
- struct npc_grimstoneAI : public npc_escortAI
+ struct npc_grimstoneAI : public EscortAI
{
- npc_grimstoneAI(Creature* creature) : npc_escortAI(creature)
+ npc_grimstoneAI(Creature* creature) : EscortAI(creature)
{
Initialize();
instance = creature->GetInstanceScript();
@@ -202,7 +202,7 @@ public:
MobDeath_Timer = 2500;
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -349,7 +349,7 @@ public:
}
if (CanWalk)
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
}
};
};
@@ -510,9 +510,9 @@ class npc_rocknot : public CreatureScript
public:
npc_rocknot() : CreatureScript("npc_rocknot") { }
- struct npc_rocknotAI : public npc_escortAI
+ struct npc_rocknotAI : public EscortAI
{
- npc_rocknotAI(Creature* creature) : npc_escortAI(creature)
+ npc_rocknotAI(Creature* creature) : EscortAI(creature)
{
Initialize();
instance = creature->GetInstanceScript();
@@ -543,7 +543,7 @@ public:
go->SetGoState((GOState)state);
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -597,7 +597,7 @@ public:
} else BreakDoor_Timer -= diff;
}
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
}
void QuestReward(Player* /*player*/, Quest const* quest, uint32 /*item*/) override
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.h b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.h
index 5102c58b9b6..75d4e85e8ed 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.h
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.h
@@ -73,4 +73,6 @@ inline AI* GetBlackrockDepthsAI(T* obj)
return GetInstanceAI<AI>(obj, BRDScriptName);
}
+#define RegisterBlackrockDepthsCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetBlackrockDepthsAI)
+
#endif
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_coren_direbrew.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_coren_direbrew.cpp
index b854239c303..77f3a4cd2e6 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_coren_direbrew.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_coren_direbrew.cpp
@@ -114,309 +114,271 @@ Position const AntagonistPos[3] =
{ 896.2667f, -130.483f, -49.66249f, 2.600541f }
};
-class boss_coren_direbrew : public CreatureScript
+struct boss_coren_direbrew : public BossAI
{
-public:
- boss_coren_direbrew() : CreatureScript("boss_coren_direbrew") { }
+ boss_coren_direbrew(Creature* creature) : BossAI(creature, DATA_COREN) { }
- struct boss_coren_direbrewAI : public BossAI
+ bool GossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override
{
- boss_coren_direbrewAI(Creature* creature) : BossAI(creature, DATA_COREN) { }
+ if (menuId != GOSSIP_ID)
+ return false;
- bool GossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override
+ if (gossipListId == GOSSIP_OPTION_FIGHT)
{
- if (menuId != GOSSIP_ID)
- return false;
+ Talk(SAY_INSULT, player);
+ DoAction(ACTION_START_FIGHT);
+ }
+ else if (gossipListId == GOSSIP_OPTION_APOLOGIZE)
+ CloseGossipMenuFor(player);
- if (gossipListId == GOSSIP_OPTION_FIGHT)
- {
- Talk(SAY_INSULT, player);
- DoAction(ACTION_START_FIGHT);
- }
- else if (gossipListId == GOSSIP_OPTION_APOLOGIZE)
- CloseGossipMenuFor(player);
+ return false;
+ }
- return false;
- }
+ void Reset() override
+ {
+ _Reset();
+ me->SetImmuneToPC(true);
+ me->SetFaction(FACTION_FRIENDLY);
+ events.SetPhase(PHASE_ALL);
- void Reset() override
- {
- _Reset();
- me->SetImmuneToPC(true);
- me->SetFaction(FACTION_FRIENDLY);
- events.SetPhase(PHASE_ALL);
+ for (uint8 i = 0; i < MAX_ANTAGONISTS; ++i)
+ me->SummonCreature(NPC_ANTAGONIST, AntagonistPos[i], TEMPSUMMON_DEAD_DESPAWN);
+ }
- for (uint8 i = 0; i < MAX_ANTAGONISTS; ++i)
- me->SummonCreature(NPC_ANTAGONIST, AntagonistPos[i], TEMPSUMMON_DEAD_DESPAWN);
- }
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ _EnterEvadeMode();
+ summons.DespawnAll();
+ _DespawnAtEvade(Seconds(10));
+ }
- void MoveInLineOfSight(Unit* who) override
- {
- if (!events.IsInPhase(PHASE_ALL) || who->GetTypeId() != TYPEID_PLAYER)
- return;
+ void MoveInLineOfSight(Unit* who) override
+ {
+ if (!events.IsInPhase(PHASE_ALL) || who->GetTypeId() != TYPEID_PLAYER)
+ return;
- events.SetPhase(PHASE_INTRO);
- events.ScheduleEvent(EVENT_INTRO_1, Seconds(6), 0, PHASE_INTRO);
- Talk(SAY_INTRO);
- }
+ events.SetPhase(PHASE_INTRO);
+ events.ScheduleEvent(EVENT_INTRO_1, Seconds(6), 0, PHASE_INTRO);
+ Talk(SAY_INTRO);
+ }
- void DoAction(int32 action) override
+ void DoAction(int32 action) override
+ {
+ if (action == ACTION_START_FIGHT)
{
- if (action == ACTION_START_FIGHT)
- {
- events.SetPhase(PHASE_ONE);
- me->SetImmuneToPC(false);
- me->SetFaction(FACTION_GOBLIN_DARK_IRON_BAR_PATRON);
- me->SetInCombatWithZone();
+ events.SetPhase(PHASE_ONE);
+ me->SetImmuneToPC(false);
+ me->SetFaction(FACTION_GOBLIN_DARK_IRON_BAR_PATRON);
+ me->SetInCombatWithZone();
- EntryCheckPredicate pred(NPC_ANTAGONIST);
- summons.DoAction(ACTION_ANTAGONIST_HOSTILE, pred);
+ EntryCheckPredicate pred(NPC_ANTAGONIST);
+ summons.DoAction(ACTION_ANTAGONIST_HOSTILE, pred);
- events.ScheduleEvent(EVENT_SUMMON_MOLE_MACHINE, Seconds(15));
- events.ScheduleEvent(EVENT_DIREBREW_DISARM, Seconds(20));
- }
+ events.ScheduleEvent(EVENT_SUMMON_MOLE_MACHINE, Seconds(15));
+ events.ScheduleEvent(EVENT_DIREBREW_DISARM, Seconds(20));
}
+ }
- void DamageTaken(Unit* /*attacker*/, uint32& damage) override
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
+ {
+ if (me->HealthBelowPctDamaged(66, damage) && events.IsInPhase(PHASE_ONE))
{
- if (me->HealthBelowPctDamaged(66, damage) && events.IsInPhase(PHASE_ONE))
- {
- events.SetPhase(PHASE_TWO);
- SummonSister(NPC_ILSA_DIREBREW);
- }
- else if (me->HealthBelowPctDamaged(33, damage) && events.IsInPhase(PHASE_TWO))
- {
- events.SetPhase(PHASE_THREE);
- SummonSister(NPC_URSULA_DIREBREW);
- }
+ events.SetPhase(PHASE_TWO);
+ SummonSister(NPC_ILSA_DIREBREW);
}
-
- void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
+ else if (me->HealthBelowPctDamaged(33, damage) && events.IsInPhase(PHASE_TWO))
{
- if (summon->GetEntry() == NPC_ILSA_DIREBREW)
- events.ScheduleEvent(EVENT_RESPAWN_ILSA, Seconds(1));
- else if (summon->GetEntry() == NPC_URSULA_DIREBREW)
- events.ScheduleEvent(EVENT_RESPAWN_URSULA, Seconds(1));
+ events.SetPhase(PHASE_THREE);
+ SummonSister(NPC_URSULA_DIREBREW);
}
+ }
- void JustDied(Unit* /*killer*/) override
- {
- _JustDied();
+ void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
+ {
+ if (summon->GetEntry() == NPC_ILSA_DIREBREW)
+ events.ScheduleEvent(EVENT_RESPAWN_ILSA, Seconds(1));
+ else if (summon->GetEntry() == NPC_URSULA_DIREBREW)
+ events.ScheduleEvent(EVENT_RESPAWN_URSULA, Seconds(1));
+ }
- Map::PlayerList const& players = me->GetMap()->GetPlayers();
- if (!players.isEmpty())
- {
- if (Group* group = players.begin()->GetSource()->GetGroup())
- if (group->isLFGGroup())
- sLFGMgr->FinishDungeon(group->GetGUID(), 287, me->GetMap());
- }
- }
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
- void SummonSister(uint32 entry)
+ Map::PlayerList const& players = me->GetMap()->GetPlayers();
+ if (!players.isEmpty())
{
- if (Creature* sister = me->SummonCreature(entry, me->GetPosition(), TEMPSUMMON_DEAD_DESPAWN))
- sister->SetInCombatWithZone();
+ if (Group* group = players.begin()->GetSource()->GetGroup())
+ if (group->isLFGGroup())
+ sLFGMgr->FinishDungeon(group->GetGUID(), 287, me->GetMap());
}
+ }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO))
- return;
+ void SummonSister(uint32 entry)
+ {
+ if (Creature* sister = me->SummonCreature(entry, me->GetPosition(), TEMPSUMMON_DEAD_DESPAWN))
+ sister->SetInCombatWithZone();
+ }
- events.Update(diff);
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO))
+ return;
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ events.Update(diff);
- while (uint32 eventId = events.ExecuteEvent())
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- switch (eventId)
+ case EVENT_INTRO_1:
+ Talk(SAY_INTRO1);
+ events.ScheduleEvent(EVENT_INTRO_2, Seconds(4), 0, PHASE_INTRO);
+ break;
+ case EVENT_INTRO_2:
{
- case EVENT_INTRO_1:
- Talk(SAY_INTRO1);
- events.ScheduleEvent(EVENT_INTRO_2, Seconds(4), 0, PHASE_INTRO);
- break;
- case EVENT_INTRO_2:
- {
- EntryCheckPredicate pred(NPC_ANTAGONIST);
- summons.DoAction(ACTION_ANTAGONIST_SAY_1, pred);
- events.ScheduleEvent(EVENT_INTRO_3, Seconds(3), 0, PHASE_INTRO);
- break;
- }
- case EVENT_INTRO_3:
- {
- Talk(SAY_INTRO2);
- EntryCheckPredicate pred(NPC_ANTAGONIST);
- summons.DoAction(ACTION_ANTAGONIST_SAY_2, pred);
- break;
- }
- case EVENT_RESPAWN_ILSA:
- SummonSister(NPC_ILSA_DIREBREW);
- break;
- case EVENT_RESPAWN_URSULA:
- SummonSister(NPC_URSULA_DIREBREW);
- break;
- case EVENT_SUMMON_MOLE_MACHINE:
- DoCastAOE(SPELL_MOLE_MACHINE_TARGET_PICKER);
- events.Repeat(Seconds(15));
- break;
- case EVENT_DIREBREW_DISARM:
- DoCastSelf(SPELL_DIREBREW_DISARM_PRE_CAST, true);
- events.Repeat(Seconds(20));
- break;
- default:
- break;
+ EntryCheckPredicate pred(NPC_ANTAGONIST);
+ summons.DoAction(ACTION_ANTAGONIST_SAY_1, pred);
+ events.ScheduleEvent(EVENT_INTRO_3, Seconds(3), 0, PHASE_INTRO);
+ break;
}
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ case EVENT_INTRO_3:
+ {
+ Talk(SAY_INTRO2);
+ EntryCheckPredicate pred(NPC_ANTAGONIST);
+ summons.DoAction(ACTION_ANTAGONIST_SAY_2, pred);
+ break;
+ }
+ case EVENT_RESPAWN_ILSA:
+ SummonSister(NPC_ILSA_DIREBREW);
+ break;
+ case EVENT_RESPAWN_URSULA:
+ SummonSister(NPC_URSULA_DIREBREW);
+ break;
+ case EVENT_SUMMON_MOLE_MACHINE:
+ me->CastCustomSpell(SPELL_MOLE_MACHINE_TARGET_PICKER, SPELLVALUE_MAX_TARGETS, 1, nullptr, true);
+ events.Repeat(Seconds(15));
+ break;
+ case EVENT_DIREBREW_DISARM:
+ DoCastSelf(SPELL_DIREBREW_DISARM_PRE_CAST, true);
+ events.Repeat(Seconds(20));
+ break;
+ default:
+ break;
}
- DoMeleeAttackIfReady();
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
- };
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackrockDepthsAI<boss_coren_direbrewAI>(creature);
+ DoMeleeAttackIfReady();
}
};
-class npc_coren_direbrew_sisters : public CreatureScript
+struct npc_coren_direbrew_sisters : public ScriptedAI
{
-public:
- npc_coren_direbrew_sisters() : CreatureScript("npc_coren_direbrew_sisters") { }
+ npc_coren_direbrew_sisters(Creature* creature) : ScriptedAI(creature) { }
- struct npc_coren_direbrew_sistersAI : public ScriptedAI
+ void SetGUID(ObjectGuid guid, int32 data) override
{
- npc_coren_direbrew_sistersAI(Creature* creature) : ScriptedAI(creature) { }
-
- void SetGUID(ObjectGuid guid, int32 data) override
- {
- if (data == DATA_TARGET_GUID)
- _targetGUID = guid;
- }
-
- ObjectGuid GetGUID(int32 data) const override
- {
- if (data == DATA_TARGET_GUID)
- return _targetGUID;
+ if (data == DATA_TARGET_GUID)
+ _targetGUID = guid;
+ }
- return ObjectGuid::Empty;
- }
+ ObjectGuid GetGUID(int32 data) const override
+ {
+ if (data == DATA_TARGET_GUID)
+ return _targetGUID;
- void EnterCombat(Unit* /*who*/) override
- {
- DoCastSelf(SPELL_PORT_TO_COREN);
+ return ObjectGuid::Empty;
+ }
- if (me->GetEntry() == NPC_URSULA_DIREBREW)
- DoCastSelf(SPELL_BARRELED_CONTROL_AURA);
- else
- DoCastSelf(SPELL_SEND_MUG_CONTROL_AURA);
+ void EnterCombat(Unit* /*who*/) override
+ {
+ DoCastSelf(SPELL_PORT_TO_COREN);
- _scheduler
- .SetValidator([this]
- {
- return !me->HasUnitState(UNIT_STATE_CASTING);
- })
- .Schedule(Seconds(2), [this](TaskContext mugChuck)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, false, true, -SPELL_HAS_DARK_BREWMAIDENS_BREW))
- DoCast(target, SPELL_CHUCK_MUG);
- mugChuck.Repeat(Seconds(4));
- });
- }
+ if (me->GetEntry() == NPC_URSULA_DIREBREW)
+ DoCastSelf(SPELL_BARRELED_CONTROL_AURA);
+ else
+ DoCastSelf(SPELL_SEND_MUG_CONTROL_AURA);
- void UpdateAI(uint32 diff) override
+ _scheduler
+ .SetValidator([this]
{
- _scheduler.Update(diff, [this]
- {
- DoMeleeAttackIfReady();
- });
- }
-
- private:
- ObjectGuid _targetGUID;
- TaskScheduler _scheduler;
- };
+ return !me->HasUnitState(UNIT_STATE_CASTING);
+ })
+ .Schedule(Seconds(2), [this](TaskContext mugChuck)
+ {
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, false, true, -SPELL_HAS_DARK_BREWMAIDENS_BREW))
+ DoCast(target, SPELL_CHUCK_MUG);
+ mugChuck.Repeat(Seconds(4));
+ });
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void UpdateAI(uint32 diff) override
{
- return GetBlackrockDepthsAI<npc_coren_direbrew_sistersAI>(creature);
+ _scheduler.Update(diff, [this]
+ {
+ DoMeleeAttackIfReady();
+ });
}
+
+private:
+ ObjectGuid _targetGUID;
+ TaskScheduler _scheduler;
};
-class npc_direbrew_minion : public CreatureScript
+struct npc_direbrew_minion : public ScriptedAI
{
-public:
- npc_direbrew_minion() : CreatureScript("npc_direbrew_minion") { }
+ npc_direbrew_minion(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
- struct npc_direbrew_minionAI : public ScriptedAI
+ void Reset() override
{
- npc_direbrew_minionAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
-
- void Reset() override
- {
- me->SetFaction(FACTION_GOBLIN_DARK_IRON_BAR_PATRON);
- DoCastAOE(SPELL_MOLE_MACHINE_EMERGE, true);
- me->SetInCombatWithZone();
- }
-
- void IsSummonedBy(Unit* /*summoner*/) override
- {
- if (Creature* coren = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_COREN)))
- coren->AI()->JustSummoned(me);
- }
-
- private:
- InstanceScript* _instance;
- };
+ me->SetFaction(FACTION_GOBLIN_DARK_IRON_BAR_PATRON);
+ me->SetInCombatWithZone();
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void IsSummonedBy(Unit* /*summoner*/) override
{
- return GetBlackrockDepthsAI<npc_direbrew_minionAI>(creature);
+ if (Creature* coren = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_COREN)))
+ coren->AI()->JustSummoned(me);
}
+
+private:
+ InstanceScript* _instance;
};
-class npc_direbrew_antagonist : public CreatureScript
+struct npc_direbrew_antagonist : public ScriptedAI
{
-public:
- npc_direbrew_antagonist() : CreatureScript("npc_direbrew_antagonist") { }
+ npc_direbrew_antagonist(Creature* creature) : ScriptedAI(creature) { }
- struct npc_direbrew_antagonistAI : public ScriptedAI
+ void DoAction(int32 action) override
{
- npc_direbrew_antagonistAI(Creature* creature) : ScriptedAI(creature) { }
-
- void DoAction(int32 action) override
- {
- switch (action)
- {
- case ACTION_ANTAGONIST_SAY_1:
- Talk(SAY_ANTAGONIST_1);
- break;
- case ACTION_ANTAGONIST_SAY_2:
- Talk(SAY_ANTAGONIST_2);
- break;
- case ACTION_ANTAGONIST_HOSTILE:
- me->SetImmuneToPC(false);
- me->SetFaction(FACTION_GOBLIN_DARK_IRON_BAR_PATRON);
- me->SetInCombatWithZone();
- break;
- default:
- break;
- }
- }
-
- void EnterCombat(Unit* who) override
+ switch (action)
{
- Talk(SAY_ANTAGONIST_COMBAT, who);
- ScriptedAI::EnterCombat(who);
+ case ACTION_ANTAGONIST_SAY_1:
+ Talk(SAY_ANTAGONIST_1);
+ break;
+ case ACTION_ANTAGONIST_SAY_2:
+ Talk(SAY_ANTAGONIST_2);
+ break;
+ case ACTION_ANTAGONIST_HOSTILE:
+ me->SetImmuneToPC(false);
+ me->SetFaction(FACTION_GOBLIN_DARK_IRON_BAR_PATRON);
+ me->SetInCombatWithZone();
+ break;
+ default:
+ break;
}
- };
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void EnterCombat(Unit* who) override
{
- return GetBlackrockDepthsAI<npc_direbrew_antagonistAI>(creature);
+ Talk(SAY_ANTAGONIST_COMBAT, who);
+ ScriptedAI::EnterCombat(who);
}
};
@@ -435,12 +397,12 @@ public:
_scheduler
.Schedule(Seconds(1), [this](TaskContext /*context*/)
{
- me->UseDoorOrButton(8);
- me->CastSpell((Unit*)nullptr, SPELL_MOLE_MACHINE_EMERGE, true);
+ me->UseDoorOrButton(10000);
+ me->CastSpell(nullptr, SPELL_MOLE_MACHINE_EMERGE, true);
})
.Schedule(Seconds(4), [this](TaskContext /*context*/)
{
- if (GameObject* trap = me->FindNearestGameObject(GO_MOLE_MACHINE_TRAP, 3.0f))
+ if (GameObject* trap = me->GetLinkedTrap())
{
trap->SetLootState(GO_ACTIVATED);
trap->UseDoorOrButton();
@@ -463,236 +425,170 @@ public:
}
};
-// 47407 - Direbrew's Disarm (precast)
-class spell_direbrew_disarm : public SpellScriptLoader
-{
- public:
- spell_direbrew_disarm() : SpellScriptLoader("spell_direbrew_disarm") { }
-
- class spell_direbrew_disarm_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_direbrew_disarm_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_DIREBREW_DISARM, SPELL_DIREBREW_DISARM_GROW });
- }
-
- void PeriodicTick(AuraEffect const* /*aurEff*/)
- {
- if (Aura* aura = GetTarget()->GetAura(SPELL_DIREBREW_DISARM_GROW))
- {
- aura->SetStackAmount(aura->GetStackAmount() + 1);
- aura->SetDuration(aura->GetDuration() - 1500);
- }
- }
-
- void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- GetTarget()->CastSpell(GetTarget(), SPELL_DIREBREW_DISARM_GROW, true);
- GetTarget()->CastSpell(GetTarget(), SPELL_DIREBREW_DISARM);
- }
-
- void Register() override
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_direbrew_disarm_AuraScript::PeriodicTick, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY);
- OnEffectApply += AuraEffectRemoveFn(spell_direbrew_disarm_AuraScript::OnApply, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
- }
- };
-
- AuraScript* GetAuraScript() const override
- {
- return new spell_direbrew_disarm_AuraScript();
- }
-};
-
// 47691 - Summon Mole Machine Target Picker
-class spell_direbrew_summon_mole_machine_target_picker : public SpellScriptLoader
+class spell_direbrew_summon_mole_machine_target_picker : public SpellScript
{
- public:
- spell_direbrew_summon_mole_machine_target_picker() : SpellScriptLoader("spell_direbrew_summon_mole_machine_target_picker") { }
-
- class spell_direbrew_summon_mole_machine_target_picker_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_direbrew_summon_mole_machine_target_picker_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_MOLE_MACHINE_MINION_SUMMONER });
- }
+ PrepareSpellScript(spell_direbrew_summon_mole_machine_target_picker);
- void HandleScriptEffect(SpellEffIndex /*effIndex*/)
- {
- GetCaster()->CastSpell(GetHitUnit(), SPELL_MOLE_MACHINE_MINION_SUMMONER, true);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_MOLE_MACHINE_MINION_SUMMONER });
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_direbrew_summon_mole_machine_target_picker_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ void HandleScriptEffect(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->CastSpell(GetHitUnit(), SPELL_MOLE_MACHINE_MINION_SUMMONER, true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_direbrew_summon_mole_machine_target_picker_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_direbrew_summon_mole_machine_target_picker::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
// 47370 - Send Mug Target Picker
-class spell_send_mug_target_picker : public SpellScriptLoader
+class spell_send_mug_target_picker : public SpellScript
{
- public:
- spell_send_mug_target_picker() : SpellScriptLoader("spell_send_mug_target_picker") { }
-
- class spell_send_mug_target_picker_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_send_mug_target_picker_SpellScript);
+ PrepareSpellScript(spell_send_mug_target_picker);
- void FilterTargets(std::list<WorldObject*>& targets)
- {
- Unit* caster = GetCaster();
-
- targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_HAS_DARK_BREWMAIDENS_BREW));
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ Unit* caster = GetCaster();
- if (targets.size() > 1)
- targets.remove_if([caster](WorldObject* obj)
- {
- if (obj->GetGUID() == caster->GetAI()->GetGUID(DATA_TARGET_GUID))
- return true;
- return false;
- });
+ targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_HAS_DARK_BREWMAIDENS_BREW));
- if (targets.empty())
- return;
+ if (targets.size() > 1)
+ targets.remove_if([caster](WorldObject* obj)
+ {
+ if (obj->GetGUID() == caster->GetAI()->GetGUID(DATA_TARGET_GUID))
+ return true;
+ return false;
+ });
- WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
- targets.clear();
- targets.push_back(target);
- }
+ if (targets.empty())
+ return;
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- Unit* caster = GetCaster();
- caster->GetAI()->SetGUID(GetHitUnit()->GetGUID(), DATA_TARGET_GUID);
- caster->CastSpell(GetHitUnit(), SPELL_SEND_FIRST_MUG, true);
- }
+ WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
+ targets.clear();
+ targets.push_back(target);
+ }
- void Register() override
- {
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_send_mug_target_picker_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
- OnEffectHitTarget += SpellEffectFn(spell_send_mug_target_picker_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ caster->GetAI()->SetGUID(GetHitUnit()->GetGUID(), DATA_TARGET_GUID);
+ caster->CastSpell(GetHitUnit(), SPELL_SEND_FIRST_MUG, true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_send_mug_target_picker_SpellScript();
- }
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_send_mug_target_picker::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
+ OnEffectHitTarget += SpellEffectFn(spell_send_mug_target_picker::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
// 47344 - Request Second Mug
-class spell_request_second_mug : public SpellScriptLoader
+class spell_request_second_mug : public SpellScript
{
- public:
- spell_request_second_mug() : SpellScriptLoader("spell_request_second_mug") { }
-
- class spell_request_second_mug_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_request_second_mug_SpellScript);
+ PrepareSpellScript(spell_request_second_mug);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_SEND_SECOND_MUG });
- }
-
- void HandleScriptEffect(SpellEffIndex /*effIndex*/)
- {
- GetHitUnit()->CastSpell(GetCaster(), SPELL_SEND_SECOND_MUG, true);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SEND_SECOND_MUG });
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_request_second_mug_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ void HandleScriptEffect(SpellEffIndex /*effIndex*/)
+ {
+ GetHitUnit()->CastSpell(GetCaster(), SPELL_SEND_SECOND_MUG, true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_request_second_mug_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_request_second_mug::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
// 47369 - Send Mug Control Aura
-class spell_send_mug_control_aura : public SpellScriptLoader
+class spell_send_mug_control_aura : public AuraScript
{
- public:
- spell_send_mug_control_aura() : SpellScriptLoader("spell_send_mug_control_aura") { }
-
- class spell_send_mug_control_aura_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_send_mug_control_aura_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_SEND_MUG_TARGET_PICKER });
- }
+ PrepareAuraScript(spell_send_mug_control_aura);
- void PeriodicTick(AuraEffect const* /*aurEff*/)
- {
- GetTarget()->CastSpell(GetTarget(), SPELL_SEND_MUG_TARGET_PICKER, true);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SEND_MUG_TARGET_PICKER });
+ }
- void Register() override
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_send_mug_control_aura_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
- }
- };
+ void PeriodicTick(AuraEffect const* /*aurEff*/)
+ {
+ GetTarget()->CastSpell(GetTarget(), SPELL_SEND_MUG_TARGET_PICKER, true);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_send_mug_control_aura_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_send_mug_control_aura::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
};
// 50278 - Barreled Control Aura
-class spell_barreled_control_aura : public SpellScriptLoader
+class spell_barreled_control_aura : public AuraScript
{
- public:
- spell_barreled_control_aura() : SpellScriptLoader("spell_barreled_control_aura") { }
+ PrepareAuraScript(spell_barreled_control_aura);
- class spell_barreled_control_aura_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_barreled_control_aura_AuraScript);
+ void PeriodicTick(AuraEffect const* /*aurEff*/)
+ {
+ PreventDefaultAction();
+ GetTarget()->CastSpell(nullptr, SPELL_BARRELED, true);
+ }
- void PeriodicTick(AuraEffect const* /*aurEff*/)
- {
- PreventDefaultAction();
- GetTarget()->CastSpell((Unit*)nullptr, SPELL_BARRELED, true);
- }
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_barreled_control_aura::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
+};
- void Register() override
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_barreled_control_aura_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
- }
- };
+// 47407 - Direbrew's Disarm (precast)
+class spell_direbrew_disarm : public AuraScript
+{
+ PrepareAuraScript(spell_direbrew_disarm);
- AuraScript* GetAuraScript() const override
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_DIREBREW_DISARM, SPELL_DIREBREW_DISARM_GROW });
+ }
+
+ void PeriodicTick(AuraEffect const* /*aurEff*/)
+ {
+ if (Aura* aura = GetTarget()->GetAura(SPELL_DIREBREW_DISARM_GROW))
{
- return new spell_barreled_control_aura_AuraScript();
+ aura->SetStackAmount(aura->GetStackAmount() + 1);
+ aura->SetDuration(aura->GetDuration() - 1500);
}
+ }
+
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->CastSpell(GetTarget(), SPELL_DIREBREW_DISARM_GROW, true);
+ GetTarget()->CastSpell(GetTarget(), SPELL_DIREBREW_DISARM);
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_direbrew_disarm::PeriodicTick, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY);
+ OnEffectApply += AuraEffectRemoveFn(spell_direbrew_disarm::OnApply, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
};
void AddSC_boss_coren_direbrew()
{
- new boss_coren_direbrew();
- new npc_coren_direbrew_sisters();
- new npc_direbrew_minion();
- new npc_direbrew_antagonist();
+ RegisterBlackrockDepthsCreatureAI(boss_coren_direbrew);
+ RegisterBlackrockDepthsCreatureAI(npc_coren_direbrew_sisters);
+ RegisterBlackrockDepthsCreatureAI(npc_direbrew_minion);
+ RegisterBlackrockDepthsCreatureAI(npc_direbrew_antagonist);
new go_direbrew_mole_machine();
- new spell_direbrew_disarm();
- new spell_direbrew_summon_mole_machine_target_picker();
- new spell_send_mug_target_picker();
- new spell_request_second_mug();
- new spell_send_mug_control_aura();
- new spell_barreled_control_aura();
+ RegisterSpellScript(spell_direbrew_summon_mole_machine_target_picker);
+ RegisterSpellScript(spell_send_mug_target_picker);
+ RegisterSpellScript(spell_request_second_mug);
+ RegisterAuraScript(spell_send_mug_control_aura);
+ RegisterAuraScript(spell_barreled_control_aura);
+ RegisterAuraScript(spell_direbrew_disarm);
}
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp
index 076966a2acb..105b27e711e 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp
@@ -355,7 +355,7 @@ public:
nefarian->setActive(true);
nefarian->SetCanFly(true);
nefarian->SetDisableGravity(true);
- nefarian->CastSpell((Unit*)nullptr, SPELL_SHADOWFLAME_INITIAL);
+ nefarian->CastSpell(nullptr, SPELL_SHADOWFLAME_INITIAL);
nefarian->GetMotionMaster()->MovePoint(1, NefarianLoc[1]);
}
events.CancelEvent(EVENT_MIND_CONTROL);
diff --git a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp
index 83d0fdcc943..b965e3063e9 100644
--- a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp
+++ b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp
@@ -94,9 +94,9 @@ public:
return GetGnomereganAI<npc_blastmaster_emi_shortfuseAI>(creature);
}
- struct npc_blastmaster_emi_shortfuseAI : public npc_escortAI
+ struct npc_blastmaster_emi_shortfuseAI : public EscortAI
{
- npc_blastmaster_emi_shortfuseAI(Creature* creature) : npc_escortAI(creature)
+ npc_blastmaster_emi_shortfuseAI(Creature* creature) : EscortAI(creature)
{
instance = creature->GetInstanceScript();
creature->RestoreFaction();
@@ -219,7 +219,7 @@ public:
}
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
//just in case
if (GetPlayerForEscort())
diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp
index fcd307ada07..2cb87b96262 100644
--- a/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp
+++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp
@@ -491,8 +491,7 @@ public:
{
if (axe->GetVictim())
ResetThreat(axe->GetVictim(), axe);
- if (target)
- AddThreat(target, 1000000.0f, axe);
+ AddThreat(target, 1000000.0f, axe);
}
}
}
diff --git a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp
index 8c5f57e9a8e..994dc2a989a 100644
--- a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp
+++ b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp
@@ -131,9 +131,9 @@ class npc_barnes : public CreatureScript
public:
npc_barnes() : CreatureScript("npc_barnes") { }
- struct npc_barnesAI : public npc_escortAI
+ struct npc_barnesAI : public EscortAI
{
- npc_barnesAI(Creature* creature) : npc_escortAI(creature)
+ npc_barnesAI(Creature* creature) : EscortAI(creature)
{
Initialize();
RaidWiped = false;
@@ -184,7 +184,7 @@ public:
void EnterCombat(Unit* /*who*/) override { }
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -288,7 +288,7 @@ public:
void UpdateAI(uint32 diff) override
{
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (HasEscortState(STATE_ESCORT_PAUSED))
{
diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp
index 5cf03b678f6..3a10b0f5619 100644
--- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp
+++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp
@@ -392,8 +392,7 @@ public:
for (uint8 i = 0; i < 3; ++i)
{
- Unit* target = nullptr;
- target = SelectTarget(SELECT_TARGET_RANDOM, 0);
+ Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0);
Creature* Orb = DoSpawnCreature(CREATURE_ARCANE_SPHERE, 5, 5, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000);
if (Orb && target)
@@ -564,15 +563,12 @@ public:
Rebirth = true;
}
- if (Rebirth)
+ if (Death_Timer <= diff)
{
- 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;
- }
+ 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())
diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp
index 86592f5677c..93f10b1a81e 100644
--- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp
+++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp
@@ -65,6 +65,7 @@ enum Misc
ACTION_SWITCH_PHASE = 1
};
+// @todo crystals should really be a DB creature summon group, having them in `creature` like this will cause tons of despawn/respawn bugs
class boss_selin_fireheart : public CreatureScript
{
public:
@@ -72,23 +73,15 @@ class boss_selin_fireheart : public CreatureScript
struct boss_selin_fireheartAI : public BossAI
{
- boss_selin_fireheartAI(Creature* creature) : BossAI(creature, DATA_SELIN)
- {
- _scheduledEvents = false;
- }
+ boss_selin_fireheartAI(Creature* creature) : BossAI(creature, DATA_SELIN), _scheduledEvents(false) { }
void Reset() override
{
- Crystals.clear();
- me->GetCreatureListWithEntryInGrid(Crystals, NPC_FEL_CRYSTAL, 250.0f);
+ std::list<Creature*> crystals;
+ me->GetCreatureListWithEntryInGrid(crystals, NPC_FEL_CRYSTAL, 250.0f);
- for (Creature* creature : Crystals)
- {
- if (!creature->IsAlive())
- creature->Respawn();
-
- creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- }
+ for (Creature* creature : crystals)
+ creature->Respawn(true);
_Reset();
CrystalGUID.Clear();
@@ -112,21 +105,16 @@ class boss_selin_fireheart : public CreatureScript
void SelectNearestCrystal()
{
- if (Crystals.empty())
- return;
-
- Crystals.sort(Trinity::ObjectDistanceOrderPred(me));
- if (Creature* CrystalChosen = Crystals.front())
+ if (Creature* crystal = me->FindNearestCreature(NPC_FEL_CRYSTAL, 250.0f))
{
Talk(SAY_ENERGY);
Talk(EMOTE_CRYSTAL);
- DoCast(CrystalChosen, SPELL_FEL_CRYSTAL_DUMMY);
- CrystalGUID = CrystalChosen->GetGUID();
- Crystals.remove(CrystalChosen);
-
+ DoCast(crystal, SPELL_FEL_CRYSTAL_DUMMY);
+ CrystalGUID = crystal->GetGUID();
+
float x, y, z;
- CrystalChosen->GetClosePoint(x, y, z, me->GetCombatReach(), CONTACT_DISTANCE);
+ crystal->GetClosePoint(x, y, z, me->GetCombatReach(), CONTACT_DISTANCE);
events.SetPhase(PHASE_DRAIN);
me->SetWalk(false);
@@ -136,14 +124,11 @@ class boss_selin_fireheart : public CreatureScript
void ShatterRemainingCrystals()
{
- if (Crystals.empty())
- return;
+ std::list<Creature*> crystals;
+ me->GetCreatureListWithEntryInGrid(crystals, NPC_FEL_CRYSTAL, 250.0f);
- for (Creature* crystal : Crystals)
- {
- if (crystal && crystal->IsAlive())
- crystal->KillSelf();
- }
+ for (Creature* crystal : crystals)
+ crystal->KillSelf();
}
void EnterCombat(Unit* /*who*/) override
@@ -259,7 +244,6 @@ class boss_selin_fireheart : public CreatureScript
}
private:
- std::list<Creature*> Crystals;
ObjectGuid CrystalGUID;
bool _scheduledEvents;
};
diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
index aa3b894bbe3..d11f352f6c0 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
@@ -1071,7 +1071,7 @@ class npc_scarlet_miner_cart : public CreatureScript
if (apply)
{
_playerGUID = who->GetGUID();
- me->CastSpell((Unit*)nullptr, SPELL_SUMMON_MINER, true);
+ me->CastSpell(nullptr, SPELL_SUMMON_MINER, true);
}
else
{
@@ -1107,9 +1107,9 @@ class npc_scarlet_miner : public CreatureScript
public:
npc_scarlet_miner() : CreatureScript("npc_scarlet_miner") { }
- struct npc_scarlet_minerAI : public npc_escortAI
+ struct npc_scarlet_minerAI : public EscortAI
{
- npc_scarlet_minerAI(Creature* creature) : npc_escortAI(creature)
+ npc_scarlet_minerAI(Creature* creature) : EscortAI(creature)
{
Initialize();
me->SetReactState(REACT_PASSIVE);
@@ -1138,7 +1138,7 @@ class npc_scarlet_miner : public CreatureScript
void InitWaypoint()
{
- AddWaypoint(1, 2389.03f, -5902.74f, 109.014f, 5000);
+ AddWaypoint(1, 2389.03f, -5902.74f, 109.014f, 0.f, 5000);
AddWaypoint(2, 2341.812012f, -5900.484863f, 102.619743f);
AddWaypoint(3, 2306.561279f, -5901.738281f, 91.792419f);
AddWaypoint(4, 2300.098389f, -5912.618652f, 86.014885f);
@@ -1157,7 +1157,7 @@ class npc_scarlet_miner : public CreatureScript
AddWaypoint(14, 2172.516602f, -6146.752441f, 1.074235f);
AddWaypoint(15, 2138.918457f, -6158.920898f, 1.342926f);
AddWaypoint(16, 2129.866699f, -6174.107910f, 4.380779f);
- AddWaypoint(17, 2117.709473f, -6193.830078f, 13.3542f, 10000);
+ AddWaypoint(17, 2117.709473f, -6193.830078f, 13.3542f, 0.f, 10000);
}
else
{
@@ -1165,7 +1165,7 @@ class npc_scarlet_miner : public CreatureScript
AddWaypoint(14, 2234.265625f, -6163.741211f, 0.916021f);
AddWaypoint(15, 2268.071777f, -6158.750977f, 1.822252f);
AddWaypoint(16, 2270.028320f, -6176.505859f, 6.340538f);
- AddWaypoint(17, 2271.739014f, -6195.401855f, 13.3542f, 10000);
+ AddWaypoint(17, 2271.739014f, -6195.401855f, 13.3542f, 0.f, 10000);
}
}
@@ -1176,7 +1176,7 @@ class npc_scarlet_miner : public CreatureScript
SetDespawnAtFar(false);
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -1224,7 +1224,7 @@ class npc_scarlet_miner : public CreatureScript
else
IntroTimer -= diff;
}
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
}
};
diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp
index 5e02a18caa6..968b0cd0f61 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp
@@ -201,9 +201,9 @@ class npc_koltira_deathweaver : public CreatureScript
public:
npc_koltira_deathweaver() : CreatureScript("npc_koltira_deathweaver") { }
- struct npc_koltira_deathweaverAI : public npc_escortAI
+ struct npc_koltira_deathweaverAI : public EscortAI
{
- npc_koltira_deathweaverAI(Creature* creature) : npc_escortAI(creature)
+ npc_koltira_deathweaverAI(Creature* creature) : EscortAI(creature)
{
Initialize();
me->SetReactState(REACT_DEFENSIVE);
@@ -228,7 +228,7 @@ public:
}
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -281,7 +281,7 @@ public:
void UpdateAI(uint32 uiDiff) override
{
- npc_escortAI::UpdateAI(uiDiff);
+ EscortAI::UpdateAI(uiDiff);
if (HasEscortState(STATE_ESCORT_PAUSED))
{
@@ -687,7 +687,7 @@ public:
switch (ExecuteSpeech_Counter)
{
- case 0:
+ case 0:
Talk(SAY_EXEC_START, player);
break;
case 1:
diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp
index 5484bb78c2f..61806772fcd 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp
@@ -274,9 +274,9 @@ class npc_highlord_darion_mograine : public CreatureScript
public:
npc_highlord_darion_mograine() : CreatureScript("npc_highlord_darion_mograine") { }
- struct npc_highlord_darion_mograineAI : public npc_escortAI
+ struct npc_highlord_darion_mograineAI : public EscortAI
{
- npc_highlord_darion_mograineAI(Creature* creature) : npc_escortAI(creature)
+ npc_highlord_darion_mograineAI(Creature* creature) : EscortAI(creature)
{
Reset();
}
@@ -453,7 +453,7 @@ public:
SetEscortPaused(bOnHold);
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -571,12 +571,12 @@ public:
void EnterEvadeMode(EvadeReason why) override
{
if (!bIsBattle)//do not reset self if we are in battle
- npc_escortAI::EnterEvadeMode(why);
+ EscortAI::EnterEvadeMode(why);
}
void UpdateAI(uint32 diff) override
{
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (!bIsBattle)
{
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_herod.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_herod.cpp
index 509faae7957..35d551afa71 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_herod.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_herod.cpp
@@ -149,9 +149,9 @@ public:
return GetScarletMonasteryAI<npc_scarlet_traineeAI>(creature);
}
- struct npc_scarlet_traineeAI : public npc_escortAI
+ struct npc_scarlet_traineeAI : public EscortAI
{
- npc_scarlet_traineeAI(Creature* creature) : npc_escortAI(creature)
+ npc_scarlet_traineeAI(Creature* creature) : EscortAI(creature)
{
Start_Timer = urand(1000, 6000);
}
@@ -159,7 +159,6 @@ public:
uint32 Start_Timer;
void Reset() override { }
- void WaypointReached(uint32 /*waypointId*/) override { }
void EnterCombat(Unit* /*who*/) override { }
void UpdateAI(uint32 diff) override
@@ -173,7 +172,7 @@ public:
} else Start_Timer -= diff;
}
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
}
};
};
diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_illucia_barov.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_illucia_barov.cpp
index 8db6ade664d..ae50fee187a 100644
--- a/src/server/scripts/EasternKingdoms/Scholomance/boss_illucia_barov.cpp
+++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_illucia_barov.cpp
@@ -28,10 +28,11 @@ Category: Scholomance
enum Spells
{
- SPELL_CURSEOFAGONY = 34794,
- SPELL_SHADOWSHOCK = 34799,
- SPELL_SILENCE = 34803,
- SPELL_FEAR = 34803
+ SPELL_CURSEOFAGONY = 18671,
+ SPELL_DOMINATE = 7645, // UNUSED YET added for documentation
+ SPELL_FEAR = 12542,
+ SPELL_SHADOWSHOCK = 17234,
+ SPELL_SILENCE = 12528
};
enum Events
diff --git a/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp
index 86ef68e8c4a..21585333cbf 100644
--- a/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp
+++ b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp
@@ -67,16 +67,16 @@ class npc_shadowfang_prisoner : public CreatureScript
public:
npc_shadowfang_prisoner() : CreatureScript("npc_shadowfang_prisoner") { }
- struct npc_shadowfang_prisonerAI : public npc_escortAI
+ struct npc_shadowfang_prisonerAI : public EscortAI
{
- npc_shadowfang_prisonerAI(Creature* creature) : npc_escortAI(creature)
+ npc_shadowfang_prisonerAI(Creature* creature) : EscortAI(creature)
{
instance = creature->GetInstanceScript();
}
InstanceScript* instance;
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -333,7 +333,7 @@ class spell_shadowfang_keep_haunting_spirits : public SpellScriptLoader
void HandleDummyTick(AuraEffect const* aurEff)
{
- GetTarget()->CastSpell((Unit*)nullptr, aurEff->GetAmount(), true);
+ GetTarget()->CastSpell(nullptr, aurEff->GetAmount(), true);
}
void HandleUpdatePeriodic(AuraEffect* aurEff)
diff --git a/src/server/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp b/src/server/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp
index f55ed325148..42780658f2b 100644
--- a/src/server/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp
+++ b/src/server/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp
@@ -24,6 +24,7 @@ SDCategory: Stratholme
EndScriptData */
#include "ScriptMgr.h"
+#include "AreaBoundary.h"
#include "Creature.h"
#include "EventMap.h"
#include "GameObject.h"
@@ -33,17 +34,15 @@ EndScriptData */
#include "Player.h"
#include "stratholme.h"
-enum Misc
-{
- MAX_ENCOUNTER = 6
-};
-
enum InstanceEvents
{
EVENT_BARON_RUN = 1,
EVENT_SLAUGHTER_SQUARE = 2
};
+Position const timmyTheCruelSpawnPosition = { 3625.358f, -3188.108f, 130.3985f, 4.834562f };
+EllipseBoundary const beforeScarletGate(Position(3671.158f, -3181.79f), 60.0f, 40.0f);
+
class instance_stratholme : public InstanceMapScript
{
public:
@@ -54,16 +53,22 @@ class instance_stratholme : public InstanceMapScript
instance_stratholme_InstanceMapScript(Map* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
+
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
EncounterState[i] = NOT_STARTED;
for (uint8 i = 0; i < 5; ++i)
IsSilverHandDead[i] = false;
+
+ timmySpawned = false;
+ scarletsKilled = 0;
}
uint32 EncounterState[MAX_ENCOUNTER];
+ uint8 scarletsKilled;
bool IsSilverHandDead[5];
+ bool timmySpawned;
ObjectGuid serviceEntranceGUID;
ObjectGuid gauntletGate1GUID;
@@ -82,6 +87,33 @@ class instance_stratholme : public InstanceMapScript
GuidSet abomnationGUID;
EventMap events;
+ void OnUnitDeath(Unit* who) override
+ {
+ switch (who->GetEntry())
+ {
+ case NPC_CRIMSON_GUARDSMAN:
+ case NPC_CRIMSON_CONJUROR:
+ case NPC_CRIMSON_INITATE:
+ case NPC_CRIMSON_GALLANT:
+ {
+ if (!timmySpawned)
+ {
+ Position pos = who->ToCreature()->GetHomePosition();
+ // check if they're in front of the entrance
+ if (beforeScarletGate.IsWithinBoundary(pos))
+ {
+ if (++scarletsKilled >= TIMMY_THE_CRUEL_CRUSADERS_REQUIRED)
+ {
+ instance->SummonCreature(NPC_TIMMY_THE_CRUEL, timmyTheCruelSpawnPosition);
+ timmySpawned = true;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
bool StartSlaugtherSquare()
{
//change to DONE when crystals implemented
diff --git a/src/server/scripts/EasternKingdoms/Stratholme/stratholme.h b/src/server/scripts/EasternKingdoms/Stratholme/stratholme.h
index e30d6feecdc..d82d0849863 100644
--- a/src/server/scripts/EasternKingdoms/Stratholme/stratholme.h
+++ b/src/server/scripts/EasternKingdoms/Stratholme/stratholme.h
@@ -57,6 +57,14 @@ enum STRCreatureIds
NPC_ABOM_VENOM = 10417,
NPC_BLACK_GUARD = 10394,
NPC_YSIDA = 16031,
+
+ // Scarlet side creatures
+ NPC_CRIMSON_GUARDSMAN = 10418,
+ NPC_CRIMSON_CONJUROR = 10419,
+ NPC_CRIMSON_INITATE = 10420,
+ NPC_CRIMSON_GALLANT = 10424,
+
+ NPC_TIMMY_THE_CRUEL = 10808
};
enum STRGameobjectIds
@@ -84,6 +92,13 @@ enum STRSpellIds
SPELL_BARON_ULTIMATUM = 27861
};
+enum STRMisc
+{
+ //! amount of crusade monsters required to be killed in order for timmy the cruel to spawn
+ TIMMY_THE_CRUEL_CRUSADERS_REQUIRED = 15,
+ MAX_ENCOUNTER = 6
+};
+
template <class AI, class T>
inline AI* GetStratholmeAI(T* obj)
{
diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp
index 88254211099..c58b8afac7a 100644
--- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp
+++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp
@@ -186,7 +186,7 @@ public:
Talk(YELL_KILL);
}
- void JustRespawned() override
+ void JustAppeared() override
{
Talk(YELL_BIRTH);
}
diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp
index 5dd4a3248ac..c671878d465 100644
--- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp
+++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.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
@@ -16,808 +15,782 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Boss_Kalecgos
-SD%Complete: 95
-SDComment:
-SDCategory: Sunwell_Plateau
-EndScriptData */
-
#include "ScriptMgr.h"
#include "GameObject.h"
#include "GameObjectAI.h"
#include "InstanceScript.h"
-#include "Log.h"
-#include "Map.h"
#include "MotionMaster.h"
-#include "ObjectAccessor.h"
#include "Player.h"
#include "ScriptedCreature.h"
+#include "SpellAuraEffects.h"
+#include "SpellScript.h"
#include "sunwell_plateau.h"
#include "TemporarySummon.h"
#include "WorldSession.h"
enum Yells
{
- SAY_SATH_AGGRO = 0,
- SAY_SATH_SLAY = 1,
- SAY_SATH_DEATH = 2,
- SAY_SATH_SPELL1 = 3,
- SAY_SATH_SPELL2 = 4,
-
- SAY_EVIL_AGGRO = 0,
- SAY_EVIL_SLAY = 1,
- SAY_GOOD_PLRWIN = 2,
- SAY_EVIL_ENRAGE = 3,
-
- SAY_GOOD_AGGRO = 0,
- SAY_GOOD_NEAR_DEATH = 1,
- SAY_GOOD_NEAR_DEATH2 = 2
+ SAY_SATH_AGGRO = 0,
+ SAY_SATH_SLAY = 1,
+ SAY_SATH_DEATH = 2,
+ SAY_SATH_SPELL1 = 3,
+ SAY_SATH_SPELL2 = 4,
+
+ SAY_EVIL_AGGRO = 0,
+ SAY_EVIL_SLAY = 1,
+ SAY_OUTRO_1 = 2,
+ SAY_OUTRO_2 = 3,
+ EMOTE_ENRAGE = 4,
+ SAY_ARCANE_BUFFET = 6,
+
+ SAY_GOOD_NEAR_DEATH_0 = 0,
+ SAY_GOOD_NEAR_DEATH_1 = 1,
+ SAY_GOOD_NEAR_DEATH_2 = 2,
+ SAY_GOOD_DEATH = 3
};
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
+ SPELL_SPECTRAL_BLAST = 44869,
+ SPELL_ARCANE_BUFFET = 45018,
+ SPELL_FROST_BREATH = 44799,
+ SPELL_TAIL_LASH = 45122,
+ SPELL_WILD_MAGIC_1 = 45001,
+ SPELL_WILD_MAGIC_2 = 45002,
+ SPELL_WILD_MAGIC_3 = 45004,
+ SPELL_WILD_MAGIC_4 = 45006,
+ SPELL_WILD_MAGIC_5 = 45010,
+ SPELL_WILD_MAGIC_6 = 44978,
+ SPELL_BANISH = 44836,
+ SPELL_ENRAGE = 44807,
+ SPELL_DEMONIC_VISUAL = 44800,
+ SPELL_CORRUPTION_STRIKE = 45029,
+ SPELL_AGONY_CURSE = 45032,
+ SPELL_SHADOW_BOLT = 45031,
+ SPELL_TAP_CHECK = 46732,
+ SPELL_TAP_CHECK_DAMAGE = 46733,
+ SPELL_AGONY_CURSE_VISUAL_1 = 45083,
+ SPELL_AGONY_CURSE_VISUAL_2 = 45084,
+ SPELL_AGONY_CURSE_VISUAL_3 = 45085,
+ SPELL_AGONY_CURSE_ALLY = 45034,
+ SPELL_HEROIC_STRIKE = 45026,
+ SPELL_REVITALIZE = 45027,
+ SPELL_SPECTRAL_BLAST_EFFECT = 44866,
+ SPELL_SPECTRAL_BLAST_VISUAL = 46648,
+ SPELL_SPECTRAL_REALM_TRIGGER = 44811,
+ SPELL_SPECTRAL_REALM_TELEPORT = 46019,
+ SPELL_SPECTRAL_REALM_AURA = 46021,
+ SPELL_SPECTRAL_REALM_2 = 44845,
+ SPELL_SPECTRAL_REALM_REACTION = 44852,
+ SPELL_SPECTRAL_EXHAUSTION = 44867,
+ SPELL_TELEPORT_BACK = 46020
+};
+
+enum KalecgosEvents
+{
+ EVENT_ARCANE_BUFFET = 1,
+ EVENT_FROST_BREATH,
+ EVENT_WILD_MAGIC,
+ EVENT_TAIL_LASH,
+ EVENT_SPECTRAL_BLAST,
+ EVENT_CHECK_TIMER,
+ EVENT_OUTRO_START,
+ EVENT_OUTRO_1,
+ EVENT_OUTRO_2,
+ EVENT_OUTRO_3,
+ EVENT_REVITALIZE,
+ EVENT_HEROIC_STRIKE,
+ EVENT_SHADOWBOLT,
+ EVENT_AGONY_CURSE,
+ EVENT_CORRUPTION_STRIKE
};
enum SWPActions
{
- DO_ENRAGE = 1,
- DO_BANISH = 2
+ ACTION_START_OUTRO = 1,
+ ACTION_ENRAGE
};
-enum Misc
+enum KalecSayPhases
{
- FLY_X = 1679,
- FLY_Y = 900,
- FLY_Z = 82,
- CENTER_X = 1705,
- CENTER_Y = 930,
- RADIUS = 30,
- MAX_PLAYERS_IN_SPECTRAL_REALM = 0 // over this, teleport object won't work, 0 disables check
+ PHASE_SAY_ONE = 1,
+ PHASE_SAY_TWO,
+ PHASE_SAY_THREE,
+ PHASE_SAY_FOUR,
+ PHASE_OUTRO
};
-#define DRAGON_REALM_Z 53.079f
-#define DEMON_REALM_Z -74.558f
+enum KalecgosPoints
+{
+ POINT_OUTRO_1 = 0,
+ POINT_OUTRO_2
+};
-uint32 WildMagic[] = { 44978, 45001, 45002, 45004, 45006, 45010 };
+Position const KalecgosSummonPos = { 1709.094f, 927.5035f, -74.28364f, 2.932153f };
+Position const FlyPos[2] =
+{
+ { 1704.18f, 927.999f, 57.888f },
+ { 1614.355f, 846.9694f, 119.0971f }
+};
-class boss_kalecgos : public CreatureScript
+uint32 const WildMagicSpells[6] =
{
-public:
- boss_kalecgos() : CreatureScript("boss_kalecgos") { }
+ SPELL_WILD_MAGIC_1,
+ SPELL_WILD_MAGIC_2,
+ SPELL_WILD_MAGIC_3,
+ SPELL_WILD_MAGIC_4,
+ SPELL_WILD_MAGIC_5,
+ SPELL_WILD_MAGIC_6
+};
- struct boss_kalecgosAI : public ScriptedAI
+struct boss_kalecgos : public BossAI
+{
+ boss_kalecgos(Creature* creature) : BossAI(creature, DATA_KALECGOS), _isEnraged(false), _isBanished(false) { }
+
+ void Reset() override
{
- boss_kalecgosAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- instance = creature->GetInstanceScript();
- bJustReset = false;
- me->setActive(true);
- }
+ _isEnraged = false;
+ _isBanished = false;
+ _Reset();
+ events.ScheduleEvent(EVENT_ARCANE_BUFFET, Seconds(8));
+ events.ScheduleEvent(EVENT_FROST_BREATH, Seconds(15));
+ events.ScheduleEvent(EVENT_WILD_MAGIC, Seconds(10));
+ events.ScheduleEvent(EVENT_TAIL_LASH, Seconds(25));
+ events.ScheduleEvent(EVENT_SPECTRAL_BLAST, Seconds(20), Seconds(25));
+ events.ScheduleEvent(EVENT_CHECK_TIMER, Seconds(1));
+ }
- void Initialize()
- {
- SathGUID.Clear();
- 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(EvadeReason /*why*/) override
+ {
+ if (events.IsInPhase(PHASE_OUTRO))
+ return;
- InstanceScript* instance;
+ _EnterEvadeMode();
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_SPECTRAL_REALM_AURA);
+ summons.DespawnAll();
+ DespawnPortals();
- uint32 ArcaneBuffetTimer;
- uint32 FrostBreathTimer;
- uint32 WildMagicTimer;
- uint32 SpectralBlastTimer;
- uint32 TailLashTimer;
- uint32 CheckTimer;
- uint32 TalkTimer;
- uint32 TalkSequence;
- uint32 ResetTimer;
+ if (Creature* sathrovar = instance->GetCreature(DATA_SATHROVARR))
+ _DespawnAtEvade(Seconds(10), sathrovar);
- bool isFriendly;
- bool isEnraged;
- bool isBanished;
- bool bJustReset;
+ _DespawnAtEvade(Seconds(10));
+ }
- ObjectGuid SathGUID;
+ void DespawnPortals()
+ {
+ std::vector<GameObject*> portals;
+ me->GetGameObjectListWithEntryInGrid(portals, GO_SPECTRAL_RIFT);
+ for (GameObject* portal : portals)
+ portal->Delete();
+ }
- void Reset() override
+ void DoAction(int32 action) override
+ {
+ switch (action)
{
- if (Creature* sath = instance->GetCreature(DATA_SATHROVARR))
- SathGUID = sath->GetGUID();
+ case ACTION_START_OUTRO:
+ events.ScheduleEvent(EVENT_OUTRO_START, Seconds(1));
+ break;
+ case ACTION_ENRAGE:
+ _isEnraged = true;
+ Talk(EMOTE_ENRAGE);
+ DoCastSelf(SPELL_ENRAGE, true);
+ break;
+ default:
+ break;
+ }
+ }
- instance->SetBossState(DATA_KALECGOS, NOT_STARTED);
+ void DamageTaken(Unit* who, uint32 &damage) override
+ {
+ if (damage >= me->GetHealth() && who->GetGUID() != me->GetGUID())
+ damage = 0;
+ }
- if (Creature* Sath = ObjectAccessor::GetCreature(*me, SathGUID))
- Sath->AI()->EnterEvadeMode();
+ void EnterCombat(Unit* /*who*/) override
+ {
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
+ Talk(SAY_EVIL_AGGRO);
+ _EnterCombat();
- me->SetFaction(FACTION_MONSTER);
- if (!bJustReset) //first reset at create
+ if (Creature* kalecgosHuman = me->SummonCreature(NPC_KALECGOS_HUMAN, KalecgosSummonPos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1000))
+ if (Creature* sathrovar = instance->GetCreature(DATA_SATHROVARR))
{
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE);
- me->SetDisableGravity(false);
- me->SetVisible(true);
- me->SetStandState(UNIT_STAND_STATE_SLEEP);
+ sathrovar->SetInCombatWith(kalecgosHuman);
+ kalecgosHuman->SetInCombatWith(sathrovar);
}
- me->SetFullHealth(); //dunno why it does not resets health at evade..
- }
+ }
+
+ void KilledUnit(Unit* who) override
+ {
+ if (who->GetTypeId() == TYPEID_PLAYER && roll_chance_i(50))
+ Talk(SAY_EVIL_SLAY);
+ }
+
+ void MovementInform(uint32 type, uint32 id) override
+ {
+ if (type != POINT_MOTION_TYPE)
+ return;
- void EnterEvadeMode(EvadeReason why) override
+ switch (id)
{
- bJustReset = true;
- me->SetVisible(false);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE);
- ScriptedAI::EnterEvadeMode(why);
+ case POINT_OUTRO_1:
+ Talk(SAY_OUTRO_1);
+ events.ScheduleEvent(EVENT_OUTRO_3, Seconds(9));
+ break;
+ case POINT_OUTRO_2:
+ me->SetVisible(false);
+ DespawnPortals();
+ me->KillSelf();
+ break;
+ default:
+ break;
}
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim() && !events.IsInPhase(PHASE_OUTRO))
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- void DoAction(int32 param) override
+ while (uint32 eventId = events.ExecuteEvent())
{
- switch (param)
+ switch (eventId)
{
- case DO_ENRAGE:
- isEnraged = true;
- me->CastSpell(me, SPELL_ENRAGE, true);
+ case EVENT_ARCANE_BUFFET:
+ if (roll_chance_i(20))
+ Talk(SAY_ARCANE_BUFFET);
+ DoCastAOE(SPELL_ARCANE_BUFFET);
+ events.Repeat(Seconds(8));
break;
- case DO_BANISH:
- isBanished = true;
- me->CastSpell(me, SPELL_BANISH, true);
+ case EVENT_FROST_BREATH:
+ DoCastAOE(SPELL_FROST_BREATH);
+ events.Repeat(Seconds(15));
break;
- }
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (TalkTimer)
- {
- if (!TalkSequence)
- {
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE);
- me->InterruptNonMeleeSpells(true);
- me->RemoveAllAuras();
- me->GetThreatManager().ClearAllThreat();
- 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->SetDisableGravity(false);
- me->SetVisible(true);
- me->SetStandState(UNIT_STAND_STATE_SLEEP);
- ResetTimer = 10000;
- bJustReset = false;
- } else ResetTimer -= diff;
- return;
- }
-
- if (!UpdateVictim())
- return;
+ case EVENT_TAIL_LASH:
+ DoCastAOE(SPELL_TAIL_LASH);
+ events.Repeat(Seconds(15));
+ break;
+ case EVENT_WILD_MAGIC:
+ DoCastAOE(WildMagicSpells[urand(0, 5)], true);
+ events.Repeat(Seconds(20));
+ break;
+ case EVENT_SPECTRAL_BLAST:
+ DoCastAOE(SPELL_SPECTRAL_BLAST, true);
+ events.Repeat(Seconds(20), Seconds(25));
+ break;
+ case EVENT_CHECK_TIMER:
+ if (!_isEnraged && HealthBelowPct(10))
+ DoAction(ACTION_ENRAGE);
- if (CheckTimer <= diff)
- {
- if (me->GetDistance(CENTER_X, CENTER_Y, DRAGON_REALM_Z) >= 75)
- {
- EnterEvadeMode(EVADE_REASON_BOUNDARY);
- return;
- }
- if (HealthBelowPct(10) && !isEnraged)
+ if (HealthBelowPct(1))
{
- if (Creature* Sath = ObjectAccessor::GetCreature(*me, SathGUID))
- Sath->AI()->DoAction(DO_ENRAGE);
- DoAction(DO_ENRAGE);
- }
- if (!isBanished && HealthBelowPct(1))
- {
- if (Creature* Sath = ObjectAccessor::GetCreature(*me, SathGUID))
+ if (Creature* sathrovarr = instance->GetCreature(DATA_SATHROVARR))
{
- if (Sath->HasAura(SPELL_BANISH))
+ if (sathrovarr->HasAura(SPELL_BANISH))
{
- Sath->DealDamage(Sath, Sath->GetHealth());
- return;
+ sathrovarr->CastSpell(sathrovarr, SPELL_TAP_CHECK, true);
+ break;
}
- else
- DoAction(DO_BANISH);
- }
- else
- {
- TC_LOG_ERROR("scripts", "Didn't find Shathrowar. Kalecgos event reseted.");
- EnterEvadeMode(EVADE_REASON_OTHER);
- return;
}
+ if (_isBanished)
+ break;
+
+ _isBanished = true;
+ DoCastSelf(SPELL_BANISH, true);
+ events.Reset();
}
- CheckTimer = 1000;
- } else CheckTimer -= diff;
+ events.Repeat(Seconds(1));
+ break;
+ case EVENT_OUTRO_START:
+ events.Reset();
+ events.SetPhase(PHASE_OUTRO);
+ me->SetRegenerateHealth(false);
+ me->SetReactState(REACT_PASSIVE);
+ me->InterruptNonMeleeSpells(true);
+ me->RemoveAllAttackers();
+ me->AttackStop();
+ me->SetFaction(FACTION_FRIENDLY);
+ me->RemoveAllAuras();
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ events.ScheduleEvent(EVENT_OUTRO_1, Seconds(3));
+ break;
+ case EVENT_OUTRO_1:
+ me->SetDisableGravity(true);
+ me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
+ events.ScheduleEvent(EVENT_OUTRO_2, Seconds(3));
+ break;
+ case EVENT_OUTRO_2:
+ me->GetMotionMaster()->MovePoint(POINT_OUTRO_1, FlyPos[0]);
+ break;
+ case EVENT_OUTRO_3:
+ Talk(SAY_OUTRO_2);
+ me->GetMotionMaster()->MovePoint(POINT_OUTRO_2, FlyPos[1], false);
+ break;
+ default:
+ break;
+ }
- if (ArcaneBuffetTimer <= diff)
- {
- DoCastAOE(SPELL_ARCANE_BUFFET);
- ArcaneBuffetTimer = 8000;
- } else ArcaneBuffetTimer -= diff;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
- if (FrostBreathTimer <= diff)
- {
- DoCastAOE(SPELL_FROST_BREATH);
- FrostBreathTimer = 15000;
- } else FrostBreathTimer -= diff;
+ DoMeleeAttackIfReady();
+ }
- if (TailLashTimer <= diff)
- {
- DoCastAOE(SPELL_TAIL_LASH);
- TailLashTimer = 15000;
- } else TailLashTimer -= diff;
+private:
+ bool _isEnraged;
+ bool _isBanished;
+};
- if (WildMagicTimer <= diff)
- {
- DoCastAOE(WildMagic[rand32() % 6]);
- WildMagicTimer = 20000;
- } else WildMagicTimer -= diff;
+struct boss_kalecgos_human : public ScriptedAI
+{
+ boss_kalecgos_human(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
- if (SpectralBlastTimer <= diff)
- {
- ThreatContainer::StorageType const& m_threatlist = me->GetThreatManager().getThreatList();
- std::list<Unit*> targetList;
- for (ThreatContainer::StorageType::const_iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr)
- {
- Unit* target = (*itr)->getTarget();
- if (target
- && target->GetTypeId() == TYPEID_PLAYER
- && (!target->GetVictim() || target->GetGUID() != me->EnsureVictim()->GetGUID())
- && target->GetPositionZ() > me->GetPositionZ() - 5
- && !target->HasAura(AURA_SPECTRAL_EXHAUSTION))
- {
- targetList.push_back(target);
- }
- }
- if (targetList.empty())
- {
- SpectralBlastTimer = 1000;
- return;
- }
+ void Reset() override
+ {
+ _events.Reset();
+ _events.SetPhase(PHASE_SAY_ONE);
- std::list<Unit*>::const_iterator i = targetList.begin();
- advance(i, rand32() % targetList.size());
- if ((*i))
- {
- (*i)->CastSpell((*i), SPELL_SPECTRAL_BLAST, true);
- SpectralBlastTimer = 20000 + rand32() % 5000;
- } else SpectralBlastTimer = 1000;
- } else SpectralBlastTimer -= diff;
+ if (Creature* sath = _instance->GetCreature(DATA_SATHROVARR))
+ _sathGUID = sath->GetGUID();
- DoMeleeAttackIfReady();
- }
- }
+ _events.ScheduleEvent(EVENT_REVITALIZE, Seconds(5));
+ _events.ScheduleEvent(EVENT_HEROIC_STRIKE, Seconds(3));
+ }
- void MoveInLineOfSight(Unit* who) override
- {
- if (bJustReset)//boss is invisible, don't attack
- return;
+ void JustDied(Unit* /*killer*/) override
+ {
+ Talk(SAY_GOOD_DEATH);
+ }
- if (!me->GetVictim() && me->IsValidAttackTarget(who))
- {
- float attackRadius = me->GetAttackDistance(who);
- if (me->IsWithinDistInMap(who, attackRadius))
- AttackStart(who);
- }
- }
+ void DamageTaken(Unit* who, uint32 &damage) override
+ {
+ if (who->GetGUID() != _sathGUID)
+ damage = 0;
- void DamageTaken(Unit* done_by, uint32 &damage) override
+ if (HealthBelowPct(75) && _events.IsInPhase(PHASE_SAY_ONE))
{
- if (damage >= me->GetHealth() && done_by != me)
- damage = 0;
+ Talk(SAY_GOOD_NEAR_DEATH_0);
+ _events.SetPhase(PHASE_SAY_TWO);
}
-
- void EnterCombat(Unit* /*who*/) override
+ else if (HealthBelowPct(50) && _events.IsInPhase(PHASE_SAY_TWO))
{
- me->SetStandState(UNIT_STAND_STATE_STAND);
- Talk(SAY_EVIL_AGGRO);
- DoZoneInCombat();
-
- instance->SetBossState(DATA_KALECGOS, IN_PROGRESS);
+ _events.SetPhase(PHASE_SAY_THREE);
+ Talk(SAY_GOOD_NEAR_DEATH_1);
}
-
- void KilledUnit(Unit* /*victim*/) override
+ else if (HealthBelowPct(10) && _events.IsInPhase(PHASE_SAY_THREE))
{
- Talk(SAY_EVIL_SLAY);
+ _events.SetPhase(PHASE_SAY_FOUR);
+ Talk(SAY_GOOD_NEAR_DEATH_2);
}
+ }
- void MovementInform(uint32 type, uint32 /*id*/) override
- {
- if (type != POINT_MOTION_TYPE)
- return;
- me->SetVisible(false);
- if (isFriendly)
- {
- me->setDeathState(JUST_DIED);
- me->GetMap()->ToInstanceMap()->PermBindAllPlayers();
- }
- else
- {
- me->GetMotionMaster()->MoveTargetedHome();
- TalkTimer = 1000;
- }
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- void GoodEnding()
- {
- switch (TalkSequence)
- {
- case 1:
- me->SetFaction(FACTION_FRIENDLY);
- TalkTimer = 1000;
- break;
- case 2:
- Talk(SAY_GOOD_PLRWIN);
- TalkTimer = 10000;
- break;
- case 3:
- me->SetDisableGravity(true);
- me->GetMotionMaster()->MovePoint(0, FLY_X, FLY_Y, FLY_Z);
- TalkTimer = 600000;
- break;
- default:
- break;
- }
- }
+ _events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- void BadEnding()
+ while (uint32 eventId = _events.ExecuteEvent())
{
- switch (TalkSequence)
+ switch (eventId)
{
- case 1:
- Talk(SAY_EVIL_ENRAGE);
- TalkTimer = 3000;
+ case EVENT_REVITALIZE:
+ DoCastSelf(SPELL_REVITALIZE);
+ _events.Repeat(Seconds(5));
break;
- case 2:
- me->SetDisableGravity(true);
- me->GetMotionMaster()->MovePoint(0, FLY_X, FLY_Y, FLY_Z);
- TalkTimer = 15000;
- break;
- case 3:
- EnterEvadeMode(EVADE_REASON_OTHER);
+ case EVENT_HEROIC_STRIKE:
+ DoCastVictim(SPELL_HEROIC_STRIKE);
+ _events.Repeat(Seconds(2));
break;
default:
break;
}
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
- };
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetSunwellPlateauAI<boss_kalecgosAI>(creature);
+ DoMeleeAttackIfReady();
}
+
+private:
+ InstanceScript* _instance;
+ EventMap _events;
+ ObjectGuid _sathGUID;
};
-class boss_kalec : public CreatureScript
+class CurseAgonySelector : NonTankTargetSelector
{
public:
- boss_kalec() : CreatureScript("boss_kalec") { }
+ CurseAgonySelector(Unit* source) : NonTankTargetSelector(source, true) { }
- CreatureAI* GetAI(Creature* creature) const override
+ bool operator()(WorldObject* target) const
{
- return GetSunwellPlateauAI<boss_kalecAI>(creature);
+ if (Unit* unitTarget = target->ToUnit())
+ return !NonTankTargetSelector::operator()(unitTarget)
+ || unitTarget->HasAura(SPELL_AGONY_CURSE) || unitTarget->HasAura(SPELL_AGONY_CURSE_ALLY)
+ || !unitTarget->HasAura(SPELL_SPECTRAL_REALM_AURA);
+ return false;
}
+};
- struct boss_kalecAI : public ScriptedAI
- {
- InstanceScript* instance;
+struct boss_sathrovarr : public BossAI
+{
+ boss_sathrovarr(Creature* creature) : BossAI(creature, DATA_KALECGOS), _isEnraged(false), _isBanished(false) { }
- uint32 RevitalizeTimer;
- uint32 HeroicStrikeTimer;
- uint32 YellTimer;
- uint32 YellSequence;
+ void Reset() override
+ {
+ _isEnraged = false;
+ _isBanished = false;
+ _Reset();
+ events.ScheduleEvent(EVENT_SHADOWBOLT, Seconds(7), Seconds(10));
+ events.ScheduleEvent(EVENT_AGONY_CURSE, Seconds(20));
+ events.ScheduleEvent(EVENT_CORRUPTION_STRIKE, Seconds(13));
+ events.ScheduleEvent(EVENT_CHECK_TIMER, Seconds(1));
+ }
- ObjectGuid SathGUID;
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _EnterCombat();
+ Talk(SAY_SATH_AGGRO);
+ }
- bool isEnraged; // if demon is enraged
+ void EnterEvadeMode(EvadeReason why) override
+ {
+ if (Creature* kalecgos = instance->GetCreature(DATA_KALECGOS_DRAGON))
+ kalecgos->AI()->EnterEvadeMode(why);
+ }
- boss_kalecAI(Creature* creature) : ScriptedAI(creature)
+ void SpellHit(Unit* caster, SpellInfo const* spell) override
+ {
+ if (spell->Id == SPELL_TAP_CHECK_DAMAGE)
{
- Initialize();
- instance = creature->GetInstanceScript();
+ DoCastSelf(SPELL_TELEPORT_BACK, true);
+ caster->Kill(me);
}
+ }
- void Initialize()
- {
- RevitalizeTimer = 5000;
- HeroicStrikeTimer = 3000;
- YellTimer = 5000;
- YellSequence = 0;
-
- isEnraged = false;
- }
+ void DamageTaken(Unit* who, uint32 &damage) override
+ {
+ if (damage >= me->GetHealth() && who->GetGUID() != me->GetGUID())
+ damage = 0;
+ }
- void Reset() override
+ void KilledUnit(Unit* target) override
+ {
+ if (target->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SATH_SLAY);
+ else if (Creature* kalecgosHuman = instance->GetCreature(DATA_KALECGOS_HUMAN))
{
- if (Creature* sath = instance->GetCreature(DATA_SATHROVARR))
- SathGUID = sath->GetGUID();
-
- Initialize();
+ if (kalecgosHuman->GetGUID() == target->GetGUID())
+ EnterEvadeMode(EVADE_REASON_OTHER);
}
+ }
- void DamageTaken(Unit* done_by, uint32 &damage) override
- {
- if (done_by->GetGUID() != SathGUID)
- damage = 0;
- else if (isEnraged)
- damage *= 3;
- }
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ Talk(SAY_SATH_DEATH);
+ instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_SPECTRAL_REALM_AURA);
+ if (Creature* kalecgos = instance->GetCreature(DATA_KALECGOS_DRAGON))
+ kalecgos->AI()->DoAction(ACTION_START_OUTRO);
+ }
- void UpdateAI(uint32 diff) override
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
{
- if (!me->HasAura(AURA_SPECTRAL_INVISIBILITY))
- me->CastSpell(me, AURA_SPECTRAL_INVISIBILITY, true);
-
- if (!UpdateVictim())
- return;
-
- if (YellTimer <= diff)
+ case EVENT_SHADOWBOLT:
+ if (roll_chance_i(20))
+ Talk(SAY_SATH_SPELL1);
+ DoCastAOE(SPELL_SHADOW_BOLT);
+ events.Repeat(Seconds(7), Seconds(10));
+ break;
+ case EVENT_AGONY_CURSE:
{
- switch (YellSequence)
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, CurseAgonySelector(me)))
+ DoCast(target, SPELL_AGONY_CURSE);
+ else
+ DoCastVictim(SPELL_AGONY_CURSE);
+ events.Repeat(Seconds(20));
+ break;
+ }
+ case EVENT_CORRUPTION_STRIKE:
+ if (roll_chance_i(20))
+ Talk(SAY_SATH_SPELL2);
+ DoCastVictim(SPELL_CORRUPTION_STRIKE);
+ events.Repeat(Seconds(13));
+ break;
+ case EVENT_CHECK_TIMER:
+ {
+ if (HealthBelowPct(10) && !_isEnraged)
{
- case 0:
- Talk(SAY_GOOD_AGGRO);
- ++YellSequence;
- break;
- case 1:
- if (HealthBelowPct(50))
- {
- Talk(SAY_GOOD_NEAR_DEATH);
- ++YellSequence;
- }
- break;
- case 2:
- if (HealthBelowPct(10))
+ _isEnraged = true;
+ if (Creature* kalecgos = instance->GetCreature(DATA_KALECGOS_DRAGON))
+ kalecgos->AI()->DoAction(ACTION_ENRAGE);
+ }
+
+ if (HealthBelowPct(1))
+ {
+ if (Creature* kalecgos = instance->GetCreature(DATA_KALECGOS_DRAGON))
+ {
+ if (kalecgos->HasAura(SPELL_BANISH))
{
- Talk(SAY_GOOD_NEAR_DEATH2);
- ++YellSequence;
+ DoCastSelf(SPELL_TAP_CHECK, true);
+ break;
}
+ }
+ if (_isBanished)
break;
- default:
- break;
+
+ _isBanished = true;
+ DoCastSelf(SPELL_BANISH, true);
}
- YellTimer = 5000;
+ events.Repeat(Seconds(1));
+ break;
}
-
- if (RevitalizeTimer <= diff)
- {
- DoCast(me, SPELL_REVITALIZE);
- RevitalizeTimer = 5000;
- } else RevitalizeTimer -= diff;
-
- if (HeroicStrikeTimer <= diff)
- {
- DoCastVictim(SPELL_HEROIC_STRIKE);
- HeroicStrikeTimer = 2000;
- } else HeroicStrikeTimer -= diff;
-
- DoMeleeAttackIfReady();
+ default:
+ break;
}
- };
+ }
+
+private:
+ bool _isEnraged;
+ bool _isBanished;
};
-class kalecgos_teleporter : public GameObjectScript
+class go_kalecgos_spectral_rift : public GameObjectScript
{
-public:
- kalecgos_teleporter() : GameObjectScript("kalecgos_teleporter") { }
-
- struct kalecgos_teleporterAI : public GameObjectAI
- {
- kalecgos_teleporterAI(GameObject* go) : GameObjectAI(go) { }
+ public:
+ go_kalecgos_spectral_rift() : GameObjectScript("go_kalecgos_spectral_rift") { }
- bool GossipHello(Player* player) override
+ struct go_kalecgos_spectral_riftAI : public GameObjectAI
{
-#if MAX_PLAYERS_IN_SPECTRAL_REALM > 0
- uint8 SpectralPlayers = 0;
- Map::PlayerList const& PlayerList = go->GetMap()->GetPlayers();
- for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
- {
- if (i->GetSource() && i->GetSource()->GetPositionZ() < DEMON_REALM_Z + 5)
- ++SpectralPlayers;
- }
+ go_kalecgos_spectral_riftAI(GameObject* go) : GameObjectAI(go) { }
- if (player->HasAura(AURA_SPECTRAL_EXHAUSTION) || SpectralPlayers >= MAX_PLAYERS_IN_SPECTRAL_REALM)
+ bool GossipHello(Player* player) override
{
+ if (!player->HasAura(SPELL_SPECTRAL_EXHAUSTION))
+ player->CastSpell(player, SPELL_SPECTRAL_REALM_TRIGGER, true);
return true;
}
-#endif
+ };
- player->CastSpell(player, SPELL_TELEPORT_SPECTRAL, true);
- return true;
+ GameObjectAI* GetAI(GameObject* go) const override
+ {
+ return GetSunwellPlateauAI<go_kalecgos_spectral_riftAI>(go);
}
- };
-
- GameObjectAI* GetAI(GameObject* go) const override
- {
- return GetSunwellPlateauAI<kalecgos_teleporterAI>(go);
- }
};
-class boss_sathrovarr : public CreatureScript
+// 46732 - Tap Check
+class spell_kalecgos_tap_check : public SpellScript
{
-public:
- boss_sathrovarr() : CreatureScript("boss_sathrovarr") { }
+ PrepareSpellScript(spell_kalecgos_tap_check);
- CreatureAI* GetAI(Creature* creature) const override
+ bool Validate(SpellInfo const* spellInfo) override
{
- return GetSunwellPlateauAI<boss_sathrovarrAI>(creature);
+ return ValidateSpellInfo({ uint32(spellInfo->Effects[EFFECT_0].CalcValue()) });
}
- struct boss_sathrovarrAI : public ScriptedAI
+ void HandleDummy(SpellEffIndex /*effIndex*/)
{
- boss_sathrovarrAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- instance = creature->GetInstanceScript();
- }
+ GetHitUnit()->CastSpell(GetCaster(), (uint32)GetSpellInfo()->Effects[EFFECT_0].CalcValue(), true);
+ }
- void Initialize()
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_kalecgos_tap_check::HandleDummy, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+};
+
+class SpectralBlastSelector : NonTankTargetSelector
+{
+ public:
+ SpectralBlastSelector(Unit* source) : NonTankTargetSelector(source, true) { }
+
+ bool operator()(WorldObject* target) const
{
- ShadowBoltTimer = urand(7, 10) * 1000;
- AgonyCurseTimer = 20000;
- CorruptionStrikeTimer = 13000;
- CheckTimer = 1000;
- ResetThreat = 1000;
- isEnraged = false;
- isBanished = false;
+ if (Unit* unitTarget = target->ToUnit())
+ return !NonTankTargetSelector::operator()(unitTarget) ||
+ unitTarget->HasAura(SPELL_SPECTRAL_EXHAUSTION) || unitTarget->HasAura(SPELL_SPECTRAL_REALM_AURA);
+ return false;
}
+};
- InstanceScript* instance;
+// 44869 - Spectral Blast
+class spell_kalecgos_spectral_blast : public SpellScript
+{
+ PrepareSpellScript(spell_kalecgos_spectral_blast);
- uint32 CorruptionStrikeTimer;
- uint32 AgonyCurseTimer;
- uint32 ShadowBoltTimer;
- uint32 CheckTimer;
- uint32 ResetThreat;
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo(
+ {
+ SPELL_SPECTRAL_BLAST_EFFECT,
+ SPELL_SPECTRAL_BLAST_VISUAL,
+ SPELL_SPECTRAL_REALM_TRIGGER
+ });
+ }
- ObjectGuid KalecGUID;
- ObjectGuid KalecgosGUID;
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ targets.remove_if(SpectralBlastSelector(GetCaster()));
+ }
- bool isEnraged;
- bool isBanished;
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ Unit* target = GetHitUnit();
- void Reset() override
- {
- me->SetFullHealth();//dunno why it does not resets health at evade..
- me->setActive(true);
- if (Creature* kalecgos = instance->GetCreature(DATA_KALECGOS_DRAGON))
- KalecgosGUID = kalecgos->GetGUID();
- instance->SetBossState(DATA_KALECGOS, NOT_STARTED);
- if (KalecGUID)
- {
- if (Creature* Kalec = ObjectAccessor::GetCreature(*me, KalecGUID))
- Kalec->setDeathState(JUST_DIED);
- KalecGUID.Clear();
- }
+ target->CastSpell(target, SPELL_SPECTRAL_BLAST_EFFECT, true);
+ caster->CastSpell(target, SPELL_SPECTRAL_BLAST_VISUAL, true);
+ caster->CastSpell(target, SPELL_SPECTRAL_REALM_TRIGGER, true);
+ }
- Initialize();
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_kalecgos_spectral_blast::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnEffectHitTarget += SpellEffectFn(spell_kalecgos_spectral_blast::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+};
- me->CastSpell(me, AURA_DEMONIC_VISUAL, true);
- TeleportAllPlayersBack();
- }
+// 44811 - Spectral Realm
+class spell_kalecgos_spectral_realm_trigger : public SpellScript
+{
+ PrepareSpellScript(spell_kalecgos_spectral_realm_trigger);
- void EnterCombat(Unit* /*who*/) override
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- if (Creature* Kalec = me->SummonCreature(NPC_KALECGOS_HUMAN, me->GetPositionX() + 10, me->GetPositionY() + 5, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0))
- {
- KalecGUID = Kalec->GetGUID();
- me->CombatStart(Kalec);
- AddThreat(Kalec, 100.0f);
- Kalec->setActive(true);
- }
- Talk(SAY_SATH_AGGRO);
- }
+ SPELL_SPECTRAL_REALM_TELEPORT,
+ SPELL_SPECTRAL_REALM_AURA,
+ SPELL_SPECTRAL_REALM_2,
+ SPELL_SPECTRAL_REALM_REACTION
+ });
+ }
- void DamageTaken(Unit* done_by, uint32 &damage) override
- {
- if (damage >= me->GetHealth() && done_by != me)
- damage = 0;
- }
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ Unit* target = GetHitUnit();
+ target->CastSpell(target, SPELL_SPECTRAL_REALM_TELEPORT, true);
+ target->CastSpell(target, SPELL_SPECTRAL_REALM_AURA, true);
+ target->CastSpell(target, SPELL_SPECTRAL_REALM_2, true);
+ target->CastSpell(target, SPELL_SPECTRAL_REALM_REACTION, true);
+ }
- void KilledUnit(Unit* target) override
- {
- if (target->GetGUID() == KalecGUID)
- {
- TeleportAllPlayersBack();
- if (Creature* Kalecgos = ObjectAccessor::GetCreature(*me, KalecgosGUID))
- {
- ENSURE_AI(boss_kalecgos::boss_kalecgosAI, Kalecgos->AI())->TalkTimer = 1;
- ENSURE_AI(boss_kalecgos::boss_kalecgosAI, Kalecgos->AI())->isFriendly = false;
- }
- EnterEvadeMode();
- return;
- }
- Talk(SAY_SATH_SLAY);
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_kalecgos_spectral_realm_trigger::HandleDummy, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+};
+
+// 46021 - Spectral Realm
+class spell_kalecgos_spectral_realm_aura : public AuraScript
+{
+ PrepareAuraScript(spell_kalecgos_spectral_realm_aura);
- void JustDied(Unit* /*killer*/) override
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- Talk(SAY_SATH_DEATH);
- me->UpdatePosition(me->GetPositionX(), me->GetPositionY(), DRAGON_REALM_Z, me->GetOrientation());
- TeleportAllPlayersBack();
- if (Creature* Kalecgos = ObjectAccessor::GetCreature(*me, KalecgosGUID))
- {
- ENSURE_AI(boss_kalecgos::boss_kalecgosAI, Kalecgos->AI())->TalkTimer = 1;
- ENSURE_AI(boss_kalecgos::boss_kalecgosAI, Kalecgos->AI())->isFriendly = true;
- }
+ SPELL_SPECTRAL_REALM_REACTION,
+ SPELL_TELEPORT_BACK,
+ SPELL_SPECTRAL_EXHAUSTION
+ });
+ }
- instance->SetBossState(DATA_KALECGOS, DONE);
- }
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* target = GetTarget();
+ target->RemoveAurasDueToSpell(SPELL_SPECTRAL_REALM_REACTION);
+ target->CastSpell(target, SPELL_TELEPORT_BACK, true);
+ target->CastSpell(target, SPELL_SPECTRAL_EXHAUSTION, true);
+ }
- void TeleportAllPlayersBack()
- {
- Map::PlayerList const& playerList = me->GetMap()->GetPlayers();
- Position const& homePos = me->GetHomePosition();
- for (Map::PlayerList::const_iterator itr = playerList.begin(); itr != playerList.end(); ++itr)
- {
- Player* player = itr->GetSource();
- if (player->IsInDist(&homePos, 50.0f) && player->GetPositionZ() <= DEMON_REALM_Z + 10.f)
- {
- player->RemoveAura(AURA_SPECTRAL_REALM);
- player->TeleportTo(me->GetMap()->GetId(), player->GetPositionX(),
- player->GetPositionY(), DRAGON_REALM_Z + 5, player->GetOrientation());
- }
- }
- }
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_kalecgos_spectral_realm_aura::OnRemove, EFFECT_0, SPELL_AURA_MOD_INVISIBILITY_DETECT, AURA_EFFECT_HANDLE_REAL);
+ }
+};
- void DoAction(int32 param) override
- {
- 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;
- }
- }
+// 45032, 45034 - Curse of Boundless Agony
+class spell_kalecgos_curse_of_boundless_agony : public AuraScript
+{
+ PrepareAuraScript(spell_kalecgos_curse_of_boundless_agony);
- void UpdateAI(uint32 diff) override
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- if (!me->HasAura(AURA_SPECTRAL_INVISIBILITY))
- me->CastSpell(me, AURA_SPECTRAL_INVISIBILITY, true);
+ SPELL_AGONY_CURSE_VISUAL_1,
+ SPELL_AGONY_CURSE_VISUAL_2,
+ SPELL_AGONY_CURSE_VISUAL_3,
+ SPELL_AGONY_CURSE_ALLY
+ });
+ }
- if (!UpdateVictim())
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (InstanceScript* instance = GetTarget()->GetInstanceScript())
+ if (instance->GetBossState(DATA_KALECGOS) == IN_PROGRESS)
return;
- if (CheckTimer <= diff)
- {
- Creature* Kalec = ObjectAccessor::GetCreature(*me, KalecGUID);
- if (!Kalec || !Kalec->IsAlive())
- {
- if (Creature* Kalecgos = ObjectAccessor::GetCreature(*me, KalecgosGUID))
- Kalecgos->AI()->EnterEvadeMode();
- return;
- }
-
- if (HealthBelowPct(10) && !isEnraged)
- {
- if (Creature* Kalecgos = ObjectAccessor::GetCreature(*me, KalecgosGUID))
- Kalecgos->AI()->DoAction(DO_ENRAGE);
- DoAction(DO_ENRAGE);
- }
-
- Creature* Kalecgos = ObjectAccessor::GetCreature(*me, KalecgosGUID);
- if (Kalecgos && !Kalecgos->IsInCombat())
- {
- EnterEvadeMode();
- return;
- }
-
- if (!isBanished && HealthBelowPct(1))
- {
- if (Kalecgos)
- {
- if (Kalecgos->HasAura(SPELL_BANISH))
- {
- me->DealDamage(me, me->GetHealth());
- return;
- }
- DoAction(DO_BANISH);
- }
- else
- {
- EnterEvadeMode();
- return;
- }
- }
- CheckTimer = 1000;
- } else CheckTimer -= diff;
+ Remove(AURA_REMOVE_BY_CANCEL);
+ }
- if (ResetThreat <= diff)
- {
- ThreatContainer::StorageType threatlist = me->GetThreatManager().getThreatList();
- for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
- {
- if (Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()))
- if (unit->GetPositionZ() > me->GetPositionZ() + 5)
- me->GetThreatManager().ModifyThreatByPercent(unit, -100);
- }
- ResetThreat = 1000;
- } else ResetThreat -= diff;
+ void OnPeriodic(AuraEffect const* aurEff)
+ {
+ if (aurEff->GetTickNumber() <= 5)
+ GetTarget()->CastSpell(GetTarget(), SPELL_AGONY_CURSE_VISUAL_1, true);
+ else if (aurEff->GetTickNumber() <= 10)
+ GetTarget()->CastSpell(GetTarget(), SPELL_AGONY_CURSE_VISUAL_2, true);
+ else
+ GetTarget()->CastSpell(GetTarget(), SPELL_AGONY_CURSE_VISUAL_3, true);
+ }
- if (ShadowBoltTimer <= diff)
- {
- if (!(rand32() % 5))
- Talk(SAY_SATH_SPELL1);
- DoCast(me, SPELL_SHADOW_BOLT);
- ShadowBoltTimer = 7000 + (rand32() % 3000);
- } else ShadowBoltTimer -= diff;
+ void HandleEffectPeriodicUpdate(AuraEffect* aurEff)
+ {
+ if (aurEff->GetTickNumber() > 1 && aurEff->GetTickNumber() % 5 == 1)
+ aurEff->SetAmount(aurEff->GetAmount() * 2);
+ }
- if (AgonyCurseTimer <= diff)
- {
- Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1);
- if (!target)
- target = me->GetVictim();
- DoCast(target, SPELL_AGONY_CURSE);
- AgonyCurseTimer = 20000;
- } else AgonyCurseTimer -= diff;
-
- if (CorruptionStrikeTimer <= diff)
- {
- if (!(rand32() % 5))Talk(SAY_SATH_SPELL2);
- DoCastVictim(SPELL_CORRUPTION_STRIKE);
- CorruptionStrikeTimer = 13000;
- } else CorruptionStrikeTimer -= diff;
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_CANCEL)
+ GetTarget()->CastSpell(GetTarget(), SPELL_AGONY_CURSE_ALLY, true);
+ }
- DoMeleeAttackIfReady();
- }
- };
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_kalecgos_curse_of_boundless_agony::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_kalecgos_curse_of_boundless_agony::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
+ OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_kalecgos_curse_of_boundless_agony::HandleEffectPeriodicUpdate, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_kalecgos_curse_of_boundless_agony::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
+ }
};
void AddSC_boss_kalecgos()
{
- new boss_kalecgos();
- new boss_sathrovarr();
- new boss_kalec();
- new kalecgos_teleporter();
+ RegisterSunwellPlateauCreatureAI(boss_kalecgos);
+ RegisterSunwellPlateauCreatureAI(boss_sathrovarr);
+ RegisterSunwellPlateauCreatureAI(boss_kalecgos_human);
+ new go_kalecgos_spectral_rift();
+ RegisterSpellScript(spell_kalecgos_tap_check);
+ RegisterSpellScript(spell_kalecgos_spectral_blast);
+ RegisterSpellScript(spell_kalecgos_spectral_realm_trigger);
+ RegisterAuraScript(spell_kalecgos_spectral_realm_aura);
+ RegisterAuraScript(spell_kalecgos_curse_of_boundless_agony);
}
diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp
index f0bcb9dd3de..ae9725525a1 100644
--- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp
+++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp
@@ -124,7 +124,7 @@ class VoidSpawnSummon : public BasicEvent
bool Execute(uint64 /*time*/, uint32 /*diff*/)
{
- _owner->CastSpell((Unit*)nullptr, SPELL_SUMMON_VOID_SENTINEL, true);
+ _owner->CastSpell(nullptr, SPELL_SUMMON_VOID_SENTINEL, true);
return true;
}
@@ -589,7 +589,7 @@ class spell_summon_blood_elves_script : SpellScriptLoader
void HandleScript(SpellEffIndex /*effIndex*/)
{
for (uint8 i = 0; i < MAX_SUMMON_BLOOD_ELVES; ++i)
- GetCaster()->CastSpell((Unit*)nullptr, SummonBloodElvesSpells[urand(0,3)], true);
+ GetCaster()->CastSpell(nullptr, SummonBloodElvesSpells[urand(0,3)], true);
}
void Register() override
@@ -621,7 +621,7 @@ class spell_muru_darkness : SpellScriptLoader
void HandleAfterCast()
{
for (uint8 i = 0; i < MAX_SUMMON_DARK_FIEND; ++i)
- GetCaster()->CastSpell((Unit*)nullptr, SummonDarkFiendSpells[i], true);
+ GetCaster()->CastSpell(nullptr, SummonDarkFiendSpells[i], true);
}
void Register() override
@@ -683,7 +683,7 @@ class spell_transform_visual_missile_periodic : public SpellScriptLoader
void OnPeriodic(AuraEffect const* /*aurEff*/)
{
- GetTarget()->CastSpell((Unit*)nullptr, RAND(TRANSFORM_VISUAL_MISSILE_1, TRANSFORM_VISUAL_MISSILE_2), true);
+ GetTarget()->CastSpell(nullptr, RAND(TRANSFORM_VISUAL_MISSILE_1, TRANSFORM_VISUAL_MISSILE_2), true);
}
void Register() override
@@ -709,7 +709,7 @@ class spell_summon_blood_elves_periodic : public SpellScriptLoader
void OnPeriodic(AuraEffect const* /*aurEff*/)
{
- GetTarget()->CastSpell((Unit*)nullptr, SPELL_SUMMON_BLOOD_ELVES_SCRIPT, true);
+ GetTarget()->CastSpell(nullptr, SPELL_SUMMON_BLOOD_ELVES_SCRIPT, true);
}
void Register() override
diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp
index 6b3c2b1bcaf..e5df84f8ba1 100644
--- a/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp
+++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp
@@ -16,6 +16,7 @@
*/
#include "ScriptMgr.h"
+#include "AreaBoundary.h"
#include "InstanceScript.h"
#include "Log.h"
#include "Map.h"
@@ -60,6 +61,11 @@ ObjectData const creatureData[] =
{ 0, 0 } // END
};
+BossBoundaryData const boundaries =
+{
+ { DATA_KALECGOS, new BoundaryUnionBoundary(new CircleBoundary(Position(1704.9f, 928.4f), 34.0), new RectangleBoundary(1689.2f, 1713.3f, 762.2f, 1074.8f)) }
+};
+
class instance_sunwell_plateau : public InstanceMapScript
{
public:
@@ -73,6 +79,7 @@ class instance_sunwell_plateau : public InstanceMapScript
SetBossNumber(EncounterCount);
LoadDoorData(doorData);
LoadObjectData(creatureData, nullptr);
+ LoadBossBoundaries(boundaries);
}
Player const* GetPlayerInMap() const
diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h b/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h
index cec43582958..85fbde015fb 100644
--- a/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h
+++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h
@@ -111,7 +111,8 @@ enum SWPGameObjectIds
GO_BOSS_COLLISION_2 = 188524,
GO_FIRE_BARRIER = 188075,
GO_MURUS_GATE_1 = 187990,
- GO_MURUS_GATE_2 = 188118
+ GO_MURUS_GATE_2 = 188118,
+ GO_SPECTRAL_RIFT = 187055
};
template <class AI, class T>
@@ -120,4 +121,6 @@ AI* GetSunwellPlateauAI(T* obj)
return GetInstanceAI<AI>(obj, SunwellPlateauScriptName);
}
+#define RegisterSunwellPlateauCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetSunwellPlateauAI)
+
#endif // SUNWELL_PLATEAU_H
diff --git a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.h b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.h
index ae1323af6aa..57d738698c7 100644
--- a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.h
+++ b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.h
@@ -33,7 +33,7 @@ enum ZADataTypes
BOSS_HEXLORD = 4,
BOSS_ZULJIN = 5,
MAX_ENCOUNTER,
-
+
DATA_GONGEVENT,
DATA_CHESTLOOTED,
TYPE_RAND_VENDOR_1,
diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
index 371be75b9f6..047467d0338 100644
--- a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
+++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
@@ -175,16 +175,13 @@ void AddSC_instance_zulgurub();
//void AddSC_alterac_mountains();
void AddSC_arathi_highlands();
void AddSC_blasted_lands();
-void AddSC_burning_steppes();
void AddSC_duskwood();
//void AddSC_eastern_plaguelands();
void AddSC_ghostlands();
void AddSC_hinterlands();
-void AddSC_isle_of_queldanas();
void AddSC_redridge_mountains();
void AddSC_silverpine_forest();
void AddSC_stormwind_city();
-void AddSC_stranglethorn_vale();
void AddSC_swamp_of_sorrows();
void AddSC_tirisfal_glades();
void AddSC_undercity();
@@ -354,16 +351,13 @@ void AddEasternKingdomsScripts()
//AddSC_alterac_mountains();
AddSC_arathi_highlands();
AddSC_blasted_lands();
- AddSC_burning_steppes();
AddSC_duskwood();
//AddSC_eastern_plaguelands();
AddSC_ghostlands();
AddSC_hinterlands();
- AddSC_isle_of_queldanas();
AddSC_redridge_mountains();
AddSC_silverpine_forest();
AddSC_stormwind_city();
- AddSC_stranglethorn_vale();
AddSC_swamp_of_sorrows();
AddSC_tirisfal_glades();
AddSC_undercity();
diff --git a/src/server/scripts/EasternKingdoms/zone_arathi_highlands.cpp b/src/server/scripts/EasternKingdoms/zone_arathi_highlands.cpp
index 501838888ef..2d3d36d425a 100644
--- a/src/server/scripts/EasternKingdoms/zone_arathi_highlands.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_arathi_highlands.cpp
@@ -60,11 +60,11 @@ class npc_professor_phizzlethorpe : public CreatureScript
public:
npc_professor_phizzlethorpe() : CreatureScript("npc_professor_phizzlethorpe") { }
- struct npc_professor_phizzlethorpeAI : public npc_escortAI
+ struct npc_professor_phizzlethorpeAI : public EscortAI
{
- npc_professor_phizzlethorpeAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_professor_phizzlethorpeAI(Creature* creature) : EscortAI(creature) { }
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
@@ -118,14 +118,14 @@ class npc_professor_phizzlethorpe : public CreatureScript
if (quest->GetQuestId() == QUEST_SUNKEN_TREASURE)
{
Talk(SAY_PROGRESS_1, player);
- npc_escortAI::Start(false, false, player->GetGUID(), quest);
+ EscortAI::Start(false, false, player->GetGUID(), quest);
me->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_PASSIVE);
}
}
void UpdateAI(uint32 diff) override
{
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
}
};
diff --git a/src/server/scripts/EasternKingdoms/zone_burning_steppes.cpp b/src/server/scripts/EasternKingdoms/zone_burning_steppes.cpp
deleted file mode 100644
index e6170d0e65e..00000000000
--- a/src/server/scripts/EasternKingdoms/zone_burning_steppes.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.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, see <http://www.gnu.org/licenses/>.
- */
-
-/* ScriptData
-SDName: Burning_Steppes
-SD%Complete: 100
-SDComment: Quest support: 4866
-SDCategory: Burning Steppes
-EndScriptData */
-
-/* ContentData
-npc_ragged_john
-EndContentData */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "ScriptedGossip.h"
-#include "Player.h"
-
-/*######
-## npc_ragged_john
-######*/
-
-enum RaggedJohn
-{
- QUEST_MOTHERS_MILK = 4866,
- SPELL_MOTHERS_MILK = 16468,
- SPELL_WICKED_MILKING = 16472
-};
-
-class npc_ragged_john : public CreatureScript
-{
- public:
- npc_ragged_john() : CreatureScript("npc_ragged_john") { }
-
- struct npc_ragged_johnAI : public ScriptedAI
- {
- npc_ragged_johnAI(Creature* creature) : ScriptedAI(creature) { }
-
- void Reset() override { }
-
- void MoveInLineOfSight(Unit* who) override
- {
- if (who->HasAura(SPELL_MOTHERS_MILK))
- {
- if (who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 15) && who->isInAccessiblePlaceFor(me))
- {
- DoCast(who, SPELL_WICKED_MILKING);
- if (Player* player = who->ToPlayer())
- player->AreaExploredOrEventHappens(QUEST_MOTHERS_MILK);
- }
- }
-
- ScriptedAI::MoveInLineOfSight(who);
- }
-
- void EnterCombat(Unit* /*who*/) override { }
-
- bool GossipHello(Player* player) override
- {
- if (me->IsQuestGiver())
- {
- player->PrepareQuestMenu(me->GetGUID());
- SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
- }
- return true;
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_ragged_johnAI(creature);
- }
-};
-
-void AddSC_burning_steppes()
-{
- new npc_ragged_john();
-}
diff --git a/src/server/scripts/EasternKingdoms/zone_ghostlands.cpp b/src/server/scripts/EasternKingdoms/zone_ghostlands.cpp
index 5a8197d8f5f..28d942c0716 100644
--- a/src/server/scripts/EasternKingdoms/zone_ghostlands.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_ghostlands.cpp
@@ -60,11 +60,11 @@ class npc_ranger_lilatha : public CreatureScript
public:
npc_ranger_lilatha() : CreatureScript("npc_ranger_lilatha") { }
- struct npc_ranger_lilathaAI : public npc_escortAI
+ struct npc_ranger_lilathaAI : public EscortAI
{
- npc_ranger_lilathaAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_ranger_lilathaAI(Creature* creature) : EscortAI(creature) { }
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
diff --git a/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp b/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp
index af79fd66ea5..519bfe5f619 100644
--- a/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp
@@ -55,9 +55,9 @@ class npc_oox09hl : public CreatureScript
public:
npc_oox09hl() : CreatureScript("npc_oox09hl") { }
- struct npc_oox09hlAI : public npc_escortAI
+ struct npc_oox09hlAI : public EscortAI
{
- npc_oox09hlAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_oox09hlAI(Creature* creature) : EscortAI(creature) { }
void Reset() override { }
@@ -81,11 +81,11 @@ public:
me->SetStandState(UNIT_STAND_STATE_STAND);
me->SetFaction(player->GetTeam() == ALLIANCE ? FACTION_ESCORTEE_A_PASSIVE : FACTION_ESCORTEE_H_PASSIVE);
Talk(SAY_OOX_START, player);
- npc_escortAI::Start(false, false, player->GetGUID(), quest);
+ EscortAI::Start(false, false, player->GetGUID(), quest);
}
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -103,7 +103,7 @@ public:
}
}
- void WaypointStart(uint32 pointId) override
+ void WaypointStarted(uint32 pointId, uint32 /*pathId*/) override
{
switch (pointId)
{
@@ -168,9 +168,9 @@ class npc_rinji : public CreatureScript
public:
npc_rinji() : CreatureScript("npc_rinji") { }
- struct npc_rinjiAI : public npc_escortAI
+ struct npc_rinjiAI : public EscortAI
{
- npc_rinjiAI(Creature* creature) : npc_escortAI(creature)
+ npc_rinjiAI(Creature* creature) : EscortAI(creature)
{
Initialize();
_IsByOutrunner = false;
@@ -188,12 +188,12 @@ public:
Initialize();
}
- void JustRespawned() override
+ void JustAppeared() override
{
_IsByOutrunner = false;
spawnId = 0;
- npc_escortAI::JustRespawned();
+ EscortAI::JustAppeared();
}
void EnterCombat(Unit* who) override
@@ -241,11 +241,11 @@ public:
if (GameObject* go = me->FindNearestGameObject(GO_RINJI_CAGE, INTERACTION_DISTANCE))
go->UseDoorOrButton();
- npc_escortAI::Start(false, false, player->GetGUID(), quest);
+ EscortAI::Start(false, false, player->GetGUID(), quest);
}
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
diff --git a/src/server/scripts/EasternKingdoms/zone_isle_of_queldanas.cpp b/src/server/scripts/EasternKingdoms/zone_isle_of_queldanas.cpp
deleted file mode 100644
index db23c49f437..00000000000
--- a/src/server/scripts/EasternKingdoms/zone_isle_of_queldanas.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.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, see <http://www.gnu.org/licenses/>.
- */
-
-/* ScriptData
-SDName: Isle_of_Queldanas
-SD%Complete: 100
-SDComment: Quest support: 11541
-SDCategory: Isle Of Quel'Danas
-EndScriptData */
-
-/* ContentData
-npc_greengill_slave
-EndContentData */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "Player.h"
-#include "SpellInfo.h"
-
-/*######
-## npc_greengill_slave
-######*/
-
-enum GreengillSlave
-{
- NPC_DARKSPINE_MYRIDON = 25060,
- QUEST_GREENGILL_COAST = 11541,
- SPELL_ENRAGE = 45111,
- SPELL_ORB_MURLOC_CONTROL = 45109,
- SPELL_GREENGILL_SLAVE_FREED = 45110
-};
-
-class npc_greengill_slave : public CreatureScript
-{
-public:
- npc_greengill_slave() : CreatureScript("npc_greengill_slave") { }
-
- struct npc_greengill_slaveAI : public ScriptedAI
- {
- npc_greengill_slaveAI(Creature* creature) : ScriptedAI(creature) { }
-
- void SpellHit(Unit* caster, SpellInfo const* spellInfo) override
- {
- Player* player = caster->ToPlayer();
-
- if (!player)
- return;
-
- if (spellInfo->Id == SPELL_ORB_MURLOC_CONTROL && !me->HasAura(SPELL_ENRAGE))
- {
- if (player->GetQuestStatus(QUEST_GREENGILL_COAST) == QUEST_STATUS_INCOMPLETE)
- DoCast(player, SPELL_GREENGILL_SLAVE_FREED, true);
-
- DoCast(me, SPELL_ENRAGE);
-
- if (Creature* Myrmidon = me->FindNearestCreature(NPC_DARKSPINE_MYRIDON, 70))
- {
- AddThreat(Myrmidon, 100000.0f);
- AttackStart(Myrmidon);
- }
- }
- }
-
- void UpdateAI(uint32 /*diff*/) override
- {
- DoMeleeAttackIfReady();
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_greengill_slaveAI(creature);
- }
-};
-
-void AddSC_isle_of_queldanas()
-{
- new npc_greengill_slave();
-}
diff --git a/src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp b/src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp
index bcd4f9bcb37..4e4f767d989 100644
--- a/src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp
@@ -43,9 +43,9 @@ class npc_corporal_keeshan : public CreatureScript
public:
npc_corporal_keeshan() : CreatureScript("npc_corporal_keeshan") { }
- struct npc_corporal_keeshanAI : public npc_escortAI
+ struct npc_corporal_keeshanAI : public EscortAI
{
- npc_corporal_keeshanAI(Creature* creature) : npc_escortAI(creature)
+ npc_corporal_keeshanAI(Creature* creature) : EscortAI(creature)
{
Initialize();
}
@@ -69,11 +69,11 @@ public:
{
Talk(SAY_CORPORAL_1, player);
me->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_ACTIVE);
- npc_escortAI::Start(true, false, player->GetGUID(), quest);
+ EscortAI::Start(true, false, player->GetGUID(), quest);
}
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
@@ -105,7 +105,7 @@ public:
if (HasEscortState(STATE_ESCORT_NONE))
return;
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (phase)
{
diff --git a/src/server/scripts/EasternKingdoms/zone_silverpine_forest.cpp b/src/server/scripts/EasternKingdoms/zone_silverpine_forest.cpp
index 4a4e19d0225..bad77139853 100644
--- a/src/server/scripts/EasternKingdoms/zone_silverpine_forest.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_silverpine_forest.cpp
@@ -65,11 +65,11 @@ class npc_deathstalker_erland : public CreatureScript
public:
npc_deathstalker_erland() : CreatureScript("npc_deathstalker_erland") { }
- struct npc_deathstalker_erlandAI : public npc_escortAI
+ struct npc_deathstalker_erlandAI : public EscortAI
{
- npc_deathstalker_erlandAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_deathstalker_erlandAI(Creature* creature) : EscortAI(creature) { }
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
diff --git a/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp b/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp
index d883f282549..e7f5ed8866f 100644
--- a/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp
@@ -128,9 +128,9 @@ public:
return new npc_lord_gregor_lescovarAI(creature);
}
- struct npc_lord_gregor_lescovarAI : public npc_escortAI
+ struct npc_lord_gregor_lescovarAI : public EscortAI
{
- npc_lord_gregor_lescovarAI(Creature* creature) : npc_escortAI(creature)
+ npc_lord_gregor_lescovarAI(Creature* creature) : EscortAI(creature)
{
Initialize();
}
@@ -173,7 +173,7 @@ public:
}
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -264,7 +264,7 @@ public:
}
} else uiTimer -= uiDiff;
}
- npc_escortAI::UpdateAI(uiDiff);
+ EscortAI::UpdateAI(uiDiff);
if (!UpdateVictim())
return;
@@ -389,9 +389,9 @@ public:
return new npc_tyrion_spybotAI(creature);
}
- struct npc_tyrion_spybotAI : public npc_escortAI
+ struct npc_tyrion_spybotAI : public EscortAI
{
- npc_tyrion_spybotAI(Creature* creature) : npc_escortAI(creature)
+ npc_tyrion_spybotAI(Creature* creature) : EscortAI(creature)
{
Initialize();
}
@@ -410,7 +410,7 @@ public:
Initialize();
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -506,7 +506,7 @@ public:
}
} else uiTimer -= uiDiff;
}
- npc_escortAI::UpdateAI(uiDiff);
+ EscortAI::UpdateAI(uiDiff);
if (!UpdateVictim())
return;
diff --git a/src/server/scripts/EasternKingdoms/zone_stranglethorn_vale.cpp b/src/server/scripts/EasternKingdoms/zone_stranglethorn_vale.cpp
deleted file mode 100644
index 0d399cb907e..00000000000
--- a/src/server/scripts/EasternKingdoms/zone_stranglethorn_vale.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.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, see <http://www.gnu.org/licenses/>.
- */
-
-/* ScriptData
-SDName: Stranglethorn_Vale
-SD%Complete: 100
-SDComment: Quest support: 592
-SDCategory: Stranglethorn Vale
-EndScriptData */
-
-/* ContentData
-npc_yenniku
-EndContentData */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "Player.h"
-#include "SpellInfo.h"
-
-/*######
-## npc_yenniku
-######*/
-
-class npc_yenniku : public CreatureScript
-{
-public:
- npc_yenniku() : CreatureScript("npc_yenniku") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_yennikuAI(creature);
- }
-
- struct npc_yennikuAI : public ScriptedAI
- {
- npc_yennikuAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- bReset = false;
- }
-
- void Initialize()
- {
- Reset_Timer = 0;
- }
-
- uint32 Reset_Timer;
- bool bReset;
-
- void Reset() override
- {
- Initialize();
- me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE);
- }
-
- void SpellHit(Unit* caster, SpellInfo const* spell) override
- {
- if (bReset || spell->Id != 3607)
- return;
-
- if (Player* player = caster->ToPlayer())
- {
- if (player->GetQuestStatus(592) == QUEST_STATUS_INCOMPLETE) //Yenniku's Release
- {
- me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN);
- me->CombatStop(); //stop combat
- me->GetThreatManager().ClearAllThreat(); //unsure of this
- me->SetFaction(FACTION_HORDE_GENERIC);
-
- bReset = true;
- Reset_Timer = 60000;
- }
- }
- }
-
- void EnterCombat(Unit* /*who*/) override { }
-
- void UpdateAI(uint32 diff) override
- {
- if (bReset)
- {
- if (Reset_Timer <= diff)
- {
- EnterEvadeMode();
- bReset = false;
- me->SetFaction(FACTION_TROLL_BLOODSCALP);
- return;
- }
-
- Reset_Timer -= diff;
-
- if (me->IsInCombat() && me->GetVictim())
- {
- if (Player* player = me->EnsureVictim()->ToPlayer())
- {
- if (player->GetTeam() == HORDE)
- {
- me->CombatStop();
- me->GetThreatManager().ClearAllThreat();
- }
- }
- }
- }
-
- //Return since we have no target
- if (!UpdateVictim())
- return;
-
- DoMeleeAttackIfReady();
- }
- };
-};
-
-/*######
-##
-######*/
-
-void AddSC_stranglethorn_vale()
-{
- new npc_yenniku();
-}
diff --git a/src/server/scripts/EasternKingdoms/zone_swamp_of_sorrows.cpp b/src/server/scripts/EasternKingdoms/zone_swamp_of_sorrows.cpp
index e0396397889..fcc2ea370ec 100644
--- a/src/server/scripts/EasternKingdoms/zone_swamp_of_sorrows.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_swamp_of_sorrows.cpp
@@ -43,9 +43,9 @@ class npc_galen_goodward : public CreatureScript
public:
npc_galen_goodward() : CreatureScript("npc_galen_goodward") { }
- struct npc_galen_goodwardAI : public npc_escortAI
+ struct npc_galen_goodwardAI : public EscortAI
{
- npc_galen_goodwardAI(Creature* creature) : npc_escortAI(creature)
+ npc_galen_goodwardAI(Creature* creature) : EscortAI(creature)
{
galensCageGUID.Clear();
Reset();
@@ -67,11 +67,11 @@ public:
if (quest->GetQuestId() == QUEST_GALENS_ESCAPE)
{
Talk(SAY_QUEST_ACCEPTED, player);
- npc_escortAI::Start(false, false, player->GetGUID(), quest);
+ EscortAI::Start(false, false, player->GetGUID(), quest);
}
}
- void WaypointStart(uint32 uiPointId) override
+ void WaypointStarted(uint32 uiPointId, uint32 /*pathId*/) override
{
switch (uiPointId)
{
@@ -95,7 +95,7 @@ public:
}
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -118,7 +118,7 @@ public:
void UpdateAI(uint32 diff) override
{
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (HasEscortState(STATE_ESCORT_NONE))
return;
diff --git a/src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp b/src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp
index 374dd3ef5c4..2a7178d6fcb 100644
--- a/src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp
@@ -42,9 +42,15 @@ EndContentData */
enum Calvin
{
- SAY_COMPLETE = 0,
- SPELL_DRINK = 2639, // possibly not correct spell (but iconId is correct)
- QUEST_590 = 590
+ SAY_COMPLETE = 0,
+ SPELL_DRINK = 7737, // Possibly incorrect spell, but both duration and icon are correct
+ QUEST_590 = 590,
+
+ EVENT_EMOTE_RUDE = 1,
+ EVENT_TALK = 2,
+ EVENT_DRINK = 3,
+ EVENT_SET_QUESTGIVER_FLAG = 4,
+ EVENT_STAND = 5
};
class npc_calvin_montague : public CreatureScript
@@ -54,82 +60,59 @@ public:
struct npc_calvin_montagueAI : public ScriptedAI
{
- npc_calvin_montagueAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- }
-
- void Initialize()
- {
- m_uiPhase = 0;
- m_uiPhaseTimer = 5000;
- m_uiPlayerGUID.Clear();
- }
-
- uint32 m_uiPhase;
- uint32 m_uiPhaseTimer;
- ObjectGuid m_uiPlayerGUID;
+ npc_calvin_montagueAI(Creature* creature) : ScriptedAI(creature) { }
void Reset() override
{
- Initialize();
-
me->RestoreFaction();
-
if (!me->IsImmuneToPC())
me->SetImmuneToPC(true);
}
void EnterCombat(Unit* /*who*/) override { }
- void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) override
+ void DamageTaken(Unit* /*attacker*/, uint32 &damage) override
{
- if (uiDamage > me->GetHealth() || me->HealthBelowPctDamaged(15, uiDamage))
+ if (damage > me->GetHealth() || me->HealthBelowPctDamaged(15, damage))
{
- uiDamage = 0;
-
- me->RestoreFaction();
- me->SetImmuneToPC(true);
+ damage = 0;
me->CombatStop(true);
-
- m_uiPhase = 1;
-
- if (pDoneBy->GetTypeId() == TYPEID_PLAYER)
- m_uiPlayerGUID = pDoneBy->GetGUID();
+ EnterEvadeMode();
+ _events.ScheduleEvent(EVENT_EMOTE_RUDE, Seconds(3));
}
}
void UpdateAI(uint32 diff) override
{
- if (m_uiPhase)
- {
- if (m_uiPhaseTimer <= diff)
- m_uiPhaseTimer = 7500;
- else
- {
- m_uiPhaseTimer -= diff;
- return;
- }
+ _events.Update(diff);
- switch (m_uiPhase)
+ if (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
{
- case 1:
+ case EVENT_EMOTE_RUDE:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_RUDE);
+ _events.ScheduleEvent(EVENT_TALK, Seconds(2));
+ break;
+ case EVENT_TALK:
Talk(SAY_COMPLETE);
- ++m_uiPhase;
+ _events.ScheduleEvent(EVENT_DRINK, Seconds(5));
break;
- case 2:
- if (Player* player = ObjectAccessor::GetPlayer(*me, m_uiPlayerGUID))
+ case EVENT_DRINK:
+ if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
player->AreaExploredOrEventHappens(QUEST_590);
-
- DoCast(me, SPELL_DRINK, true);
- ++m_uiPhase;
+ _playerGUID.Clear();
+ DoCastSelf(SPELL_DRINK);
+ _events.ScheduleEvent(EVENT_SET_QUESTGIVER_FLAG, Seconds(12));
+ break;
+ case EVENT_SET_QUESTGIVER_FLAG:
+ me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
+ _events.ScheduleEvent(EVENT_STAND, Seconds(3));
break;
- case 3:
- EnterEvadeMode();
+ case EVENT_STAND:
+ me->SetStandState(UNIT_STAND_STATE_STAND);
break;
}
-
- return;
}
if (!UpdateVictim())
@@ -142,11 +125,17 @@ public:
{
if (quest->GetQuestId() == QUEST_590)
{
+ _playerGUID = player->GetGUID();
me->SetFaction(FACTION_ENEMY);
me->SetImmuneToPC(false);
AttackStart(player);
+ me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
}
}
+
+ private:
+ EventMap _events;
+ ObjectGuid _playerGUID;
};
CreatureAI* GetAI(Creature* creature) const override
diff --git a/src/server/scripts/EasternKingdoms/zone_undercity.cpp b/src/server/scripts/EasternKingdoms/zone_undercity.cpp
index 37fe5cec1f9..4eaf6ce0002 100644
--- a/src/server/scripts/EasternKingdoms/zone_undercity.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_undercity.cpp
@@ -82,6 +82,11 @@ enum Sylvanas
GUID_EVENT_INVOKER = 1,
};
+enum Sounds
+{
+ SOUND_AGGRO = 5886
+};
+
float HighborneLoc[4][3]=
{
{1285.41f, 312.47f, 0.51f},
@@ -120,6 +125,7 @@ public:
void EnterCombat(Unit* /*who*/) override
{
+ DoPlaySoundToSet(me, SOUND_AGGRO);
_events.ScheduleEvent(EVENT_FADE, 30000);
_events.ScheduleEvent(EVENT_SUMMON_SKELETON, 20000);
_events.ScheduleEvent(EVENT_BLACK_ARROW, 15000);
diff --git a/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp b/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp
index 7ba95268562..159a37812a9 100644
--- a/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp
@@ -19,12 +19,11 @@
/* 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)
+SDComment: Quest support: 5097, 5098, 5216, 5219, 5222, 5225, 5229, 5231, 5233, 5235.
SDCategory: Western Plaguelands
EndScriptData */
/* ContentData
-npcs_dithers_and_arbington
npc_the_scourge_cauldron
npc_andorhal_tower
EndContentData */
@@ -36,99 +35,6 @@ EndContentData */
#include "WorldSession.h"
/*######
-## npcs_dithers_and_arbington
-######*/
-
-enum DithersAndArbington
-{
- GOSSIP_ITEM_ID_FELSTONE_FIELD = 0,
- GOSSIP_ITEM_ID_DALSON_S_TEARS = 1,
- GOSSIP_ITEM_ID_WRITHING_HAUNT = 2,
- GOSSIP_ITEM_ID_GAHRRON_S_WITH = 3,
- GOSSIP_MENU_ID_LETS_GET_TO_WORK = 3223,
- GOSSIP_MENU_ID_VITREOUS_FOCUSER = 3229,
- NPC_TEXT_OSSEOUS_AGITATORS = 3980,
- NPC_TEXT_SOMATIC_INTENSIFIERS_1 = 3981,
- NPC_TEXT_SOMATIC_INTENSIFIERS_2 = 3982,
- NPC_TEXT_ECTOPLASMIC_RESONATORS = 3983,
- NPC_TEXT_LET_S_GET_TO_WORK = 3985,
- QUEST_MISSION_ACCOMPLISHED_H = 5237,
- QUEST_MISSION_ACCOMPLISHED_A = 5238,
- CREATE_ITEM_VITREOUS_FOCUSER = 17529
-};
-
-class npcs_dithers_and_arbington : public CreatureScript
-{
- public:
- npcs_dithers_and_arbington() : CreatureScript("npcs_dithers_and_arbington") { }
-
- struct npcs_dithers_and_arbingtonAI : public ScriptedAI
- {
- npcs_dithers_and_arbingtonAI(Creature* creature) : ScriptedAI(creature) { }
-
- bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
- {
- uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
- ClearGossipMenuFor(player);
- switch (action)
- {
- case GOSSIP_ACTION_TRADE:
- player->GetSession()->SendListInventory(me->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF + 1:
- AddGossipItemFor(player, GOSSIP_MENU_ID_VITREOUS_FOCUSER, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
- SendGossipMenuFor(player, NPC_TEXT_OSSEOUS_AGITATORS, me->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF + 2:
- AddGossipItemFor(player, GOSSIP_MENU_ID_VITREOUS_FOCUSER, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
- SendGossipMenuFor(player, NPC_TEXT_SOMATIC_INTENSIFIERS_1, me->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF + 3:
- AddGossipItemFor(player, GOSSIP_MENU_ID_VITREOUS_FOCUSER, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
- SendGossipMenuFor(player, NPC_TEXT_SOMATIC_INTENSIFIERS_2, me->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF + 4:
- AddGossipItemFor(player, GOSSIP_MENU_ID_VITREOUS_FOCUSER, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
- SendGossipMenuFor(player, NPC_TEXT_ECTOPLASMIC_RESONATORS, me->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF + 5:
- CloseGossipMenuFor(player);
- DoCast(player, CREATE_ITEM_VITREOUS_FOCUSER, false);
- break;
- }
- return true;
- }
-
- bool GossipHello(Player* player) override
- {
- if (me->IsQuestGiver())
- player->PrepareQuestMenu(me->GetGUID());
-
- if (me->IsVendor())
- AddGossipItemFor(player, GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
-
- if (player->GetQuestRewardStatus(QUEST_MISSION_ACCOMPLISHED_H) || player->GetQuestRewardStatus(QUEST_MISSION_ACCOMPLISHED_A))
- {
- AddGossipItemFor(player, GOSSIP_MENU_ID_LETS_GET_TO_WORK, GOSSIP_ITEM_ID_FELSTONE_FIELD, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- AddGossipItemFor(player, GOSSIP_MENU_ID_LETS_GET_TO_WORK, GOSSIP_ITEM_ID_DALSON_S_TEARS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
- AddGossipItemFor(player, GOSSIP_MENU_ID_LETS_GET_TO_WORK, GOSSIP_ITEM_ID_WRITHING_HAUNT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
- AddGossipItemFor(player, GOSSIP_MENU_ID_LETS_GET_TO_WORK, GOSSIP_ITEM_ID_GAHRRON_S_WITH, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
- SendGossipMenuFor(player, NPC_TEXT_LET_S_GET_TO_WORK, me->GetGUID());
- }
- else
- SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
-
- return true;
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npcs_dithers_and_arbingtonAI(creature);
- }
-};
-
-/*######
## npc_the_scourge_cauldron
######*/
@@ -248,7 +154,6 @@ public:
void AddSC_western_plaguelands()
{
- new npcs_dithers_and_arbington();
new npc_the_scourge_cauldron();
new npc_andorhal_tower();
}
diff --git a/src/server/scripts/EasternKingdoms/zone_wetlands.cpp b/src/server/scripts/EasternKingdoms/zone_wetlands.cpp
index 51dbdf19a03..6120b89ee2b 100644
--- a/src/server/scripts/EasternKingdoms/zone_wetlands.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_wetlands.cpp
@@ -56,9 +56,9 @@ public:
return new npc_tapoke_slim_jahnAI(creature);
}
- struct npc_tapoke_slim_jahnAI : public npc_escortAI
+ struct npc_tapoke_slim_jahnAI : public EscortAI
{
- npc_tapoke_slim_jahnAI(Creature* creature) : npc_escortAI(creature)
+ npc_tapoke_slim_jahnAI(Creature* creature) : EscortAI(creature)
{
Initialize();
}
@@ -76,7 +76,7 @@ public:
Initialize();
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
diff --git a/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp b/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp
index 921af01bfb4..a026506bb9d 100644
--- a/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp
+++ b/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp
@@ -223,16 +223,16 @@ class npc_morridune : public CreatureScript
public:
npc_morridune() : CreatureScript("npc_morridune") { }
- struct npc_morriduneAI : public npc_escortAI
+ struct npc_morriduneAI : public EscortAI
{
- npc_morriduneAI(Creature* creature) : npc_escortAI(creature)
+ npc_morriduneAI(Creature* creature) : EscortAI(creature)
{
Talk(SAY_MORRIDUNE_1);
me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
Start(false);
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp
index b41eb13c46c..885d611e3bc 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp
@@ -99,7 +99,7 @@ public:
Talk(SAY_ONSLAY);
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (waypointId == 7)
{
@@ -121,8 +121,8 @@ public:
{
if (IsEvent)
{
- //Must update npc_escortAI
- npc_escortAI::UpdateAI(diff);
+ //Must update EscortAI
+ EscortAI::UpdateAI(diff);
if (!go)
{
go = true;
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp
index 985f4e214a8..5e3ba51b1ca 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp
@@ -102,7 +102,7 @@ public:
Talk(SAY_ONSLAY);
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (waypointId == 7 && instance)
{
@@ -124,8 +124,8 @@ public:
{
if (IsEvent)
{
- //Must update npc_escortAI
- npc_escortAI::UpdateAI(diff);
+ //Must update EscortAI
+ EscortAI::UpdateAI(diff);
if (!go)
{
go = true;
@@ -225,10 +225,6 @@ public:
{
}
- void WaypointReached(uint32 /*waypointId*/) override
- {
- }
-
void MoveInLineOfSight(Unit* who) override
{
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp
index 25c174cb26a..fc26c35a314 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp
@@ -97,7 +97,7 @@ public:
Talk(SAY_ONSLAY);
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (waypointId == 7 && instance)
{
@@ -119,8 +119,8 @@ public:
{
if (IsEvent)
{
- //Must update npc_escortAI
- npc_escortAI::UpdateAI(diff);
+ //Must update EscortAI
+ EscortAI::UpdateAI(diff);
if (!go)
{
go = true;
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp
index d1677b2c8ef..746350853b9 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp
@@ -92,7 +92,7 @@ public:
Talk(SAY_ONSLAY);
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (waypointId == 7 && instance)
{
@@ -114,8 +114,8 @@ public:
{
if (IsEvent)
{
- //Must update npc_escortAI
- npc_escortAI::UpdateAI(diff);
+ //Must update EscortAI
+ EscortAI::UpdateAI(diff);
if (!go)
{
go = true;
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp
index 48b8e59a5a7..ec918cbb3a4 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp
@@ -316,7 +316,7 @@ float HordeFirePos[65][8]=//spawn points for the fire visuals (GO) in the horde
{5545.43f, -2647.82f, 1483.05f, 5.38848f, 0, 0, 0.432578f, -0.901596f}
};
-hyjalAI::hyjalAI(Creature* creature) : npc_escortAI(creature), Summons(me)
+hyjalAI::hyjalAI(Creature* creature) : EscortAI(creature), Summons(me)
{
Initialize();
instance = creature->GetInstanceScript();
@@ -447,7 +447,7 @@ void hyjalAI::MoveInLineOfSight(Unit* who)
if (IsDummy)
return;
- npc_escortAI::MoveInLineOfSight(who);
+ EscortAI::MoveInLineOfSight(who);
}
void hyjalAI::SummonCreature(uint32 entry, float Base[4][3])
@@ -930,7 +930,7 @@ void hyjalAI::RespawnNearPos(float x, float y)
Cell::VisitGridObjects(x, y, me->GetMap(), worker, me->GetGridActivationRange());
}
-void hyjalAI::WaypointReached(uint32 waypointId)
+void hyjalAI::WaypointReached(uint32 waypointId, uint32 /*pathId*/)
{
if (waypointId == 1 || (waypointId == 0 && me->GetEntry() == THRALL))
{
@@ -979,7 +979,7 @@ void hyjalAI::WaypointReached(uint32 waypointId)
}
void hyjalAI::DoOverrun(uint32 faction, const uint32 diff)
{
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (WaitForTeleport)
{
if (TeleportTimer <= diff)
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h
index a61a568f61b..9a0c1f78b92 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h
@@ -115,7 +115,7 @@ enum YellId
DEATH = 6, // Used on death
};
-struct hyjalAI : public npc_escortAI
+struct hyjalAI : public EscortAI
{
hyjalAI(Creature* creature);
@@ -144,7 +144,7 @@ struct hyjalAI : public npc_escortAI
void SummonedCreatureDespawn(Creature* summoned) override;
void HideNearPos(float x, float y);
void RespawnNearPos(float x, float y);
- void WaypointReached(uint32 waypointId) override;
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override;
void DoOverrun(uint32 faction, const uint32 diff);
void MoveInLineOfSight(Unit* who) override;
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp
index f9cd454c67e..6d05e6094b1 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp
@@ -176,7 +176,7 @@ float HordeOverrunWP[21][3]=//waypoints in the horde base used in the end in the
{5429.91f, -2718.44f, 1493.42f}//20 end 2
};
-hyjal_trashAI::hyjal_trashAI(Creature* creature) : npc_escortAI(creature)
+hyjal_trashAI::hyjal_trashAI(Creature* creature) : EscortAI(creature)
{
instance = creature->GetInstanceScript();
IsEvent = false;
@@ -443,7 +443,7 @@ public:
void EnterCombat(Unit* /*who*/) override { }
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (waypointId == 0 && !IsOverrun)
{
@@ -498,7 +498,7 @@ public:
if (!CanMove)return;
hyjal_trashAI::UpdateAI(diff);
if (IsEvent || IsOverrun)
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (IsEvent)
{
if (!go)
@@ -558,7 +558,7 @@ public:
KnockDownTimer = 10000;
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (waypointId == 7 && !IsOverrun)
{
@@ -590,7 +590,7 @@ public:
{
hyjal_trashAI::UpdateAI(diff);
if (IsEvent || IsOverrun)
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (IsEvent)
{
if (!go)
@@ -656,7 +656,7 @@ public:
RandomMove = false;
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (waypointId == 7 && !IsOverrun)
{
@@ -689,7 +689,7 @@ public:
{
hyjal_trashAI::UpdateAI(diff);
if (IsEvent || IsOverrun)
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (IsEvent)
{
if (!go)
@@ -766,7 +766,7 @@ public:
summons.Despawn(summon);
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (waypointId == 7 && !IsOverrun)
{
@@ -810,7 +810,7 @@ public:
hyjal_trashAI::UpdateAI(diff);
if (IsEvent || IsOverrun)
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (IsEvent)
{
@@ -879,7 +879,7 @@ public:
ShellTimer = 50000 + rand32() % 10000;
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (waypointId == 7 && !IsOverrun)
{
@@ -904,7 +904,7 @@ public:
{
hyjal_trashAI::UpdateAI(diff);
if (IsEvent || IsOverrun)
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (IsEvent)
{
if (!go)
@@ -975,7 +975,7 @@ public:
WebTimer = 20000 + rand32() % 5000;
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (waypointId == 7 && !IsOverrun)
{
@@ -1000,7 +1000,7 @@ public:
{
hyjal_trashAI::UpdateAI(diff);
if (IsEvent || IsOverrun)
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (IsEvent)
{
if (!go)
@@ -1061,7 +1061,7 @@ public:
ManaBurnTimer = 9000 + rand32() % 5000;
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (waypointId == 7 && !IsOverrun)
{
@@ -1086,7 +1086,7 @@ public:
{
hyjal_trashAI::UpdateAI(diff);
if (IsEvent || IsOverrun)
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (IsEvent)
{
if (!go)
@@ -1155,7 +1155,7 @@ public:
me->SetDisableGravity(true);
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (waypointId == 2 && !IsOverrun)
{
@@ -1189,7 +1189,7 @@ public:
if (IsEvent || IsOverrun)
{
ENSURE_AI(hyjal_trashAI, me->AI())->SetCanAttack(false);
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
}
if (IsEvent)
@@ -1280,7 +1280,7 @@ public:
me->SetDisableGravity(true);
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (waypointId == 2 && !IsOverrun)
{
@@ -1310,7 +1310,7 @@ public:
if (IsEvent || IsOverrun)
{
ENSURE_AI(hyjal_trashAI, me->AI())->SetCanAttack(false);
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
}
if (IsEvent)
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.h b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.h
index 66189f9c71d..d3ccbecf7ea 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.h
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.h
@@ -21,7 +21,7 @@
#include "hyjal.h"
#include "ScriptedEscortAI.h"
-struct hyjal_trashAI : public npc_escortAI
+struct hyjal_trashAI : public EscortAI
{
hyjal_trashAI(Creature* creature);
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp
index 26c718c3930..860b4a38968 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp
@@ -258,9 +258,9 @@ class npc_arthas : public CreatureScript
public:
npc_arthas() : CreatureScript("npc_arthas") { }
- struct npc_arthasAI : public npc_escortAI
+ struct npc_arthasAI : public EscortAI
{
- npc_arthasAI(Creature* creature) : npc_escortAI(creature)
+ npc_arthasAI(Creature* creature) : EscortAI(creature)
{
Initialize();
instance = creature->GetInstanceScript();
@@ -336,7 +336,7 @@ public:
void AttackStart(Unit* who) override
{
if (who && !who->IsImmuneToPC())
- npc_escortAI::AttackStart(who);
+ EscortAI::AttackStart(who);
}
void EnterCombat(Unit* /*who*/) override
@@ -391,7 +391,7 @@ public:
++step;
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -511,7 +511,7 @@ public:
void UpdateAI(uint32 diff) override
{
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (bStepping)
{
@@ -901,7 +901,7 @@ public:
}
}
else if (instance->GetBossState(bossEvent) == FAIL)
- npc_escortAI::EnterEvadeMode();
+ EscortAI::EnterEvadeMode();
else
phaseTimer = 10000;
break;
@@ -1061,7 +1061,7 @@ public:
JumpToNextStep(15000);
}
else if (instance->GetBossState(DATA_EPOCH) == FAIL)
- npc_escortAI::EnterEvadeMode();
+ EscortAI::EnterEvadeMode();
else
phaseTimer = 10000;
break;
@@ -1106,7 +1106,7 @@ public:
JumpToNextStep(1000);
}
else if (instance->GetBossState(DATA_MAL_GANIS) == FAIL)
- npc_escortAI::EnterEvadeMode();
+ EscortAI::EnterEvadeMode();
else
phaseTimer = 10000;
break;
@@ -1196,7 +1196,7 @@ public:
return false;
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
SendGossipMenuFor(player, 907, me->GetGUID());
- break;
+ break;
}
case 1:
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp
index 29e94b2bd9f..c4ba72f2563 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp
@@ -197,9 +197,9 @@ class npc_thrall_old_hillsbrad : public CreatureScript
public:
npc_thrall_old_hillsbrad() : CreatureScript("npc_thrall_old_hillsbrad") { }
- struct npc_thrall_old_hillsbradAI : public npc_escortAI
+ struct npc_thrall_old_hillsbradAI : public EscortAI
{
- npc_thrall_old_hillsbradAI(Creature* creature) : npc_escortAI(creature)
+ npc_thrall_old_hillsbradAI(Creature* creature) : EscortAI(creature)
{
Initialize();
instance = creature->GetInstanceScript();
@@ -217,7 +217,7 @@ public:
bool LowHp;
bool HadMount;
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -354,7 +354,7 @@ public:
if (Creature* Taretha = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_TARETHA)))
{
if (Player* player = GetPlayerForEscort())
- ENSURE_AI(npc_escortAI, (Taretha->AI()))->Start(false, true, player->GetGUID());
+ ENSURE_AI(EscortAI, (Taretha->AI()))->Start(false, true, player->GetGUID());
}
//kill credit Creature for quest
@@ -455,7 +455,7 @@ public:
void UpdateAI(uint32 diff) override
{
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (!UpdateVictim())
return;
@@ -564,16 +564,16 @@ class npc_taretha : public CreatureScript
public:
npc_taretha() : CreatureScript("npc_taretha") { }
- struct npc_tarethaAI : public npc_escortAI
+ struct npc_tarethaAI : public EscortAI
{
- npc_tarethaAI(Creature* creature) : npc_escortAI(creature)
+ npc_tarethaAI(Creature* creature) : EscortAI(creature)
{
instance = creature->GetInstanceScript();
}
InstanceScript* instance;
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -591,7 +591,7 @@ public:
void UpdateAI(uint32 diff) override
{
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
}
bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
diff --git a/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp b/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp
index b2ee684d0f5..131087fb683 100644
--- a/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp
+++ b/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp
@@ -46,9 +46,9 @@ class npc_willix : public CreatureScript
public:
npc_willix() : CreatureScript("npc_willix") { }
- struct npc_willixAI : public npc_escortAI
+ struct npc_willixAI : public EscortAI
{
- npc_willixAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_willixAI(Creature* creature) : EscortAI(creature) { }
void QuestAccept(Player* player, Quest const* quest) override
{
@@ -60,7 +60,7 @@ public:
}
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp
index 2a775ecf9fd..77e1ef0e77e 100644
--- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp
+++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp
@@ -204,9 +204,7 @@ public:
//Charge_Timer
if (Charge_Timer <= diff)
{
- Unit* target = nullptr;
- target = SelectTarget(SELECT_TARGET_RANDOM, 0);
- if (target)
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
DoCast(target, SPELL_CHARGE);
//me->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, true, 1);
diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp
index 3a154f40eed..0e6a24b3ee3 100644
--- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp
+++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp
@@ -122,10 +122,7 @@ public:
//ChangeTarget_Timer
if (Submerged && ChangeTarget_Timer <= diff)
{
- Unit* target = nullptr;
- target = SelectTarget(SELECT_TARGET_RANDOM, 0);
-
- if (target)
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
DoTeleportTo(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ());
ChangeTarget_Timer = urand(10000, 20000);
diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp
index bbcf18d5b84..602f5652e4a 100644
--- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp
+++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp
@@ -558,9 +558,7 @@ public:
//Blizzard_Timer
if (Blizzard_Timer <= diff)
{
- Unit* target = nullptr;
- target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45, true);
- if (target)
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45, true))
DoCast(target, SPELL_BLIZZARD);
Blizzard_Timer = 15000 + rand32() % 15000;
} else Blizzard_Timer -= diff;
diff --git a/src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.cpp b/src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.cpp
index 0286de05581..48308c9bc16 100644
--- a/src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.cpp
+++ b/src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.cpp
@@ -81,9 +81,9 @@ class npc_disciple_of_naralex : public CreatureScript
public:
npc_disciple_of_naralex() : CreatureScript("npc_disciple_of_naralex") { }
- struct npc_disciple_of_naralexAI : public npc_escortAI
+ struct npc_disciple_of_naralexAI : public EscortAI
{
- npc_disciple_of_naralexAI(Creature* creature) : npc_escortAI(creature)
+ npc_disciple_of_naralexAI(Creature* creature) : EscortAI(creature)
{
instance = creature->GetInstanceScript();
eventTimer = 0;
@@ -98,7 +98,7 @@ public:
uint32 eventProgress;
InstanceScript* instance;
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -153,7 +153,7 @@ public:
void UpdateAI(uint32 diff) override
{
if (currentEvent != TYPE_NARALEX_PART3)
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (eventTimer <= diff)
{
@@ -177,7 +177,7 @@ public:
++eventProgress;
Talk(SAY_BANISH_THE_SPIRITS);
DoCast(me, SPELL_SERPENTINE_CLEANSING);
- //CAST_AI(npc_escort::npc_escortAI, me->AI())->SetCanDefend(false);
+ //CAST_AI(EscortAI, me->AI())->SetCanDefend(false);
eventTimer = 30000;
me->SummonCreature(NPC_DEVIATE_VIPER, -61.5261f, 273.676f, -92.8442f, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000);
me->SummonCreature(NPC_DEVIATE_VIPER, -58.4658f, 280.799f, -92.8393f, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000);
@@ -186,7 +186,7 @@ public:
else
if (eventProgress == 2)
{
- //CAST_AI(npc_escort::npc_escortAI, me->AI())->SetCanDefend(true);
+ //CAST_AI(EscortAI, me->AI())->SetCanDefend(true);
Talk(SAY_CAVERNS_PURIFIED);
instance->SetData(TYPE_NARALEX_PART2, DONE);
if (me->HasAura(SPELL_SERPENTINE_CLEANSING))
@@ -206,7 +206,7 @@ public:
{
++eventProgress;
eventTimer = 15000;
- //CAST_AI(npc_escort::npc_escortAI, me->AI())->SetCanDefend(false);
+ //CAST_AI(EscortAI, me->AI())->SetCanDefend(false);
if (Creature* naralex = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_NARALEX)))
DoCast(naralex, SPELL_NARALEXS_AWAKENING, true);
Talk(EMOTE_AWAKENING_RITUAL);
diff --git a/src/server/scripts/Kalimdor/zone_ashenvale.cpp b/src/server/scripts/Kalimdor/zone_ashenvale.cpp
index f5680664e27..964c8506113 100644
--- a/src/server/scripts/Kalimdor/zone_ashenvale.cpp
+++ b/src/server/scripts/Kalimdor/zone_ashenvale.cpp
@@ -64,9 +64,9 @@ class npc_ruul_snowhoof : public CreatureScript
public:
npc_ruul_snowhoof() : CreatureScript("npc_ruul_snowhoof") { }
- struct npc_ruul_snowhoofAI : public npc_escortAI
+ struct npc_ruul_snowhoofAI : public EscortAI
{
- npc_ruul_snowhoofAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_ruul_snowhoofAI(Creature* creature) : EscortAI(creature) { }
void Reset() override
{
@@ -86,11 +86,11 @@ public:
if (quest->GetQuestId() == QUEST_FREEDOM_TO_RUUL)
{
me->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_PASSIVE);
- npc_escortAI::Start(true, false, player->GetGUID());
+ EscortAI::Start(true, false, player->GetGUID());
}
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
@@ -121,7 +121,7 @@ public:
void UpdateAI(uint32 diff) override
{
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
}
};
@@ -181,9 +181,9 @@ class npc_muglash : public CreatureScript
public:
npc_muglash() : CreatureScript("npc_muglash") { }
- struct npc_muglashAI : public npc_escortAI
+ struct npc_muglashAI : public EscortAI
{
- npc_muglashAI(Creature* creature) : npc_escortAI(creature)
+ npc_muglashAI(Creature* creature) : EscortAI(creature)
{
Initialize();
}
@@ -229,11 +229,11 @@ public:
{
Talk(SAY_MUG_START1);
me->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_PASSIVE);
- npc_escortAI::Start(true, false, player->GetGUID());
+ EscortAI::Start(true, false, player->GetGUID());
}
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (Player* player = GetPlayerForEscort())
{
@@ -291,7 +291,7 @@ public:
void UpdateAI(uint32 diff) override
{
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (!me->GetVictim())
{
diff --git a/src/server/scripts/Kalimdor/zone_azshara.cpp b/src/server/scripts/Kalimdor/zone_azshara.cpp
index 0813b05705f..bea3ac7dd73 100644
--- a/src/server/scripts/Kalimdor/zone_azshara.cpp
+++ b/src/server/scripts/Kalimdor/zone_azshara.cpp
@@ -24,104 +24,6 @@
#include "ScriptedGossip.h"
#include "SpellInfo.h"
-/*######
-## npc_spitelashes
-######*/
-
-enum Spitelashes
-{
- SPELL_POLYMORPH_RANK1 = 118,
- SPELL_POLYMORPH_RANK2 = 12824,
- SPELL_POLYMORPH_RANK3 = 12825,
- SPELL_POLYMORPH_RANK4 = 12826,
- SPELL_POLYMORPH = 29124,
- SPELL_POLYMORPH_BACKFIRE = 28406,
- SPELL_REMOVE_POLYMORPH = 6924
-};
-
-class npc_spitelashes : public CreatureScript
-{
-public:
- npc_spitelashes() : CreatureScript("npc_spitelashes") { }
-
- struct npc_spitelashesAI : public ScriptedAI
- {
- npc_spitelashesAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- }
-
- void Initialize()
- {
- morphtimer = 0;
- spellhit = false;
- }
-
- uint32 morphtimer;
- bool spellhit;
-
- void Reset() override
- {
- Initialize();
- }
-
- void EnterCombat(Unit* /*who*/) override { }
-
- void SpellHit(Unit* unit, SpellInfo const* spell) override
- {
- if (spellhit)
- return;
-
- switch (spell->Id)
- {
- case SPELL_POLYMORPH_RANK1:
- case SPELL_POLYMORPH_RANK2:
- case SPELL_POLYMORPH_RANK3:
- case SPELL_POLYMORPH_RANK4:
- if (Player* player = unit->ToPlayer())
- if (player->GetQuestStatus(9364) == QUEST_STATUS_INCOMPLETE)
- {
- spellhit = true;
- DoCast(me, SPELL_POLYMORPH);
- }
- break;
- default:
- break;
- }
- }
-
- void UpdateAI(uint32 diff) override
- {
- // 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->DespawnOrUnsummon();
- return;
- }
- // walk 5 seconds before summoning
- if (spellhit && morphtimer < 5000)
- {
- morphtimer += diff;
- if (morphtimer >= 5000)
- {
- DoCast(me, SPELL_POLYMORPH_BACKFIRE); // summon copies
- DoCast(me, SPELL_REMOVE_POLYMORPH); // visual explosion
- }
- }
- if (!UpdateVictim())
- return;
-
- /// @todo add abilities for the different creatures
- DoMeleeAttackIfReady();
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_spitelashesAI(creature);
- }
-};
-
/*####
# npc_rizzle_sprysprocket
####*/
@@ -468,7 +370,6 @@ public:
void AddSC_azshara()
{
- new npc_spitelashes();
new npc_rizzle_sprysprocket();
new npc_depth_charge();
}
diff --git a/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp b/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp
index c4036fbe836..3ce50e2f2f4 100644
--- a/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp
+++ b/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp
@@ -348,9 +348,9 @@ class npc_magwin : public CreatureScript
public:
npc_magwin() : CreatureScript("npc_magwin") { }
- struct npc_magwinAI : public npc_escortAI
+ struct npc_magwinAI : public EscortAI
{
- npc_magwinAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_magwinAI(Creature* creature) : EscortAI(creature) { }
void Reset() override
{
@@ -371,7 +371,7 @@ public:
}
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (Player* player = GetPlayerForEscort())
{
@@ -410,7 +410,7 @@ public:
break;
case EVENT_START_ESCORT:
if (Player* player = ObjectAccessor::GetPlayer(*me, _player))
- npc_escortAI::Start(true, false, player->GetGUID());
+ EscortAI::Start(true, false, player->GetGUID());
_events.ScheduleEvent(EVENT_STAND, Seconds(2));
break;
case EVENT_STAND: // Remove kneel standstate. Using a separate delayed event because it causes unwanted delay before starting waypoint movement.
@@ -428,7 +428,7 @@ public:
}
}
- npc_escortAI::UpdateEscortAI(diff);
+ EscortAI::UpdateEscortAI(diff);
}
private:
@@ -718,128 +718,6 @@ public:
}
};
-/*########
-## Quest: The Prophecy of Akida
-########*/
-
-enum BristlelimbCage
-{
- QUEST_THE_PROPHECY_OF_AKIDA = 9544,
- NPC_STILLPINE_CAPITIVE = 17375,
- GO_BRISTELIMB_CAGE = 181714,
-
- CAPITIVE_SAY = 0,
-
- POINT_INIT = 1,
- EVENT_DESPAWN = 1,
-};
-
-class npc_stillpine_capitive : public CreatureScript
-{
- public:
- npc_stillpine_capitive() : CreatureScript("npc_stillpine_capitive") { }
-
- struct npc_stillpine_capitiveAI : public ScriptedAI
- {
- npc_stillpine_capitiveAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- }
-
- void Initialize()
- {
- _playerGUID.Clear();
- _movementComplete = false;
- }
-
- void Reset() override
- {
- if (GameObject* cage = me->FindNearestGameObject(GO_BRISTELIMB_CAGE, 5.0f))
- {
- cage->SetLootState(GO_JUST_DEACTIVATED);
- cage->SetGoState(GO_STATE_READY);
- }
- _events.Reset();
- Initialize();
- }
-
- void StartMoving(Player* owner)
- {
- if (owner)
- {
- Talk(CAPITIVE_SAY, owner);
- _playerGUID = owner->GetGUID();
- }
- Position pos = me->GetNearPosition(3.0f, 0.0f);
- me->GetMotionMaster()->MovePoint(POINT_INIT, pos);
- }
-
- void MovementInform(uint32 type, uint32 id) override
- {
- if (type != POINT_MOTION_TYPE || id != POINT_INIT)
- return;
-
- if (Player* _player = ObjectAccessor::GetPlayer(*me, _playerGUID))
- _player->KilledMonsterCredit(me->GetEntry(), me->GetGUID());
-
- _movementComplete = true;
- _events.ScheduleEvent(EVENT_DESPAWN, 3500);
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (!_movementComplete)
- return;
-
- _events.Update(diff);
-
- if (_events.ExecuteEvent() == EVENT_DESPAWN)
- me->DespawnOrUnsummon();
- }
-
- private:
- ObjectGuid _playerGUID;
- EventMap _events;
- bool _movementComplete;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_stillpine_capitiveAI(creature);
- }
-};
-
-class go_bristlelimb_cage : public GameObjectScript
-{
- public:
- go_bristlelimb_cage() : GameObjectScript("go_bristlelimb_cage") { }
-
- struct go_bristlelimb_cageAI : public GameObjectAI
- {
- go_bristlelimb_cageAI(GameObject* go) : GameObjectAI(go) { }
-
- bool GossipHello(Player* player) override
- {
- me->SetGoState(GO_STATE_READY);
- if (player->GetQuestStatus(QUEST_THE_PROPHECY_OF_AKIDA) == QUEST_STATUS_INCOMPLETE)
- {
- if (Creature* capitive = me->FindNearestCreature(NPC_STILLPINE_CAPITIVE, 5.0f, true))
- {
- me->ResetDoorOrButton();
- ENSURE_AI(npc_stillpine_capitive::npc_stillpine_capitiveAI, capitive->AI())->StartMoving(player);
- return false;
- }
- }
- return true;
- }
- };
-
- GameObjectAI* GetAI(GameObject* go) const override
- {
- return new go_bristlelimb_cageAI(go);
- }
-};
-
void AddSC_azuremyst_isle()
{
new npc_draenei_survivor();
@@ -849,6 +727,4 @@ void AddSC_azuremyst_isle()
new npc_geezle();
new npc_death_ravager();
new go_ravager_cage();
- new npc_stillpine_capitive();
- new go_bristlelimb_cage();
}
diff --git a/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp b/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp
index 86eae7f4b40..3a92623ce15 100644
--- a/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp
+++ b/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp
@@ -355,9 +355,9 @@ class npc_demolitionist_legoso : public CreatureScript
public:
npc_demolitionist_legoso() : CreatureScript("npc_demolitionist_legoso") { }
- struct npc_demolitionist_legosoAI : public npc_escortAI
+ struct npc_demolitionist_legosoAI : public EscortAI
{
- npc_demolitionist_legosoAI(Creature* creature) : npc_escortAI(creature)
+ npc_demolitionist_legosoAI(Creature* creature) : EscortAI(creature)
{
Initialize();
}
@@ -466,7 +466,7 @@ public:
if (HasEscortState(STATE_ESCORT_NONE))
return;
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (_phase)
{
@@ -710,7 +710,7 @@ public:
}
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
diff --git a/src/server/scripts/Kalimdor/zone_darkshore.cpp b/src/server/scripts/Kalimdor/zone_darkshore.cpp
index b2bdd76c137..8d07fd1e506 100644
--- a/src/server/scripts/Kalimdor/zone_darkshore.cpp
+++ b/src/server/scripts/Kalimdor/zone_darkshore.cpp
@@ -204,9 +204,9 @@ class npc_prospector_remtravel : public CreatureScript
public:
npc_prospector_remtravel() : CreatureScript("npc_prospector_remtravel") { }
- struct npc_prospector_remtravelAI : public npc_escortAI
+ struct npc_prospector_remtravelAI : public EscortAI
{
- npc_prospector_remtravelAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_prospector_remtravelAI(Creature* creature) : EscortAI(creature) { }
void Reset() override { }
@@ -222,7 +222,7 @@ public:
//pSummoned->AI()->AttackStart(me);
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (Player* player = GetPlayerForEscort())
{
diff --git a/src/server/scripts/Kalimdor/zone_desolace.cpp b/src/server/scripts/Kalimdor/zone_desolace.cpp
index 4360574a65f..74786200a43 100644
--- a/src/server/scripts/Kalimdor/zone_desolace.cpp
+++ b/src/server/scripts/Kalimdor/zone_desolace.cpp
@@ -176,9 +176,9 @@ class npc_dalinda : public CreatureScript
public:
npc_dalinda() : CreatureScript("npc_dalinda") { }
- struct npc_dalindaAI : public npc_escortAI
+ struct npc_dalindaAI : public EscortAI
{
- npc_dalindaAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_dalindaAI(Creature* creature) : EscortAI(creature) { }
void Reset() override { }
@@ -191,7 +191,7 @@ public:
return;
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
@@ -209,7 +209,7 @@ public:
void UpdateAI(uint32 diff) override
{
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (!UpdateVictim())
return;
diff --git a/src/server/scripts/Kalimdor/zone_feralas.cpp b/src/server/scripts/Kalimdor/zone_feralas.cpp
index 16c30f6fadd..0d0f75d4d4d 100644
--- a/src/server/scripts/Kalimdor/zone_feralas.cpp
+++ b/src/server/scripts/Kalimdor/zone_feralas.cpp
@@ -63,11 +63,11 @@ class npc_oox22fe : public CreatureScript
public:
npc_oox22fe() : CreatureScript("npc_oox22fe") { }
- struct npc_oox22feAI : public npc_escortAI
+ struct npc_oox22feAI : public EscortAI
{
- npc_oox22feAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_oox22feAI(Creature* creature) : EscortAI(creature) { }
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
diff --git a/src/server/scripts/Kalimdor/zone_moonglade.cpp b/src/server/scripts/Kalimdor/zone_moonglade.cpp
index e19d8797bc9..792fe737c8b 100644
--- a/src/server/scripts/Kalimdor/zone_moonglade.cpp
+++ b/src/server/scripts/Kalimdor/zone_moonglade.cpp
@@ -111,10 +111,10 @@ public:
return new npc_clintar_spiritAI(creature);
}
- struct npc_clintar_spiritAI : public npc_escortAI
+ struct npc_clintar_spiritAI : public EscortAI
{
public:
- npc_clintar_spiritAI(Creature* creature) : npc_escortAI(creature)
+ npc_clintar_spiritAI(Creature* creature) : EscortAI(creature)
{
Initialize();
PlayerGUID.Clear();
@@ -189,7 +189,7 @@ public:
AttackStart(player->getAttackerForHelper());
return;
}
- npc_escortAI::EnterEvadeMode(why);
+ EscortAI::EnterEvadeMode(why);
}
void StartEvent(Player* player)
@@ -198,7 +198,7 @@ public:
{
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]);
+ AddWaypoint(i, Clintar_spirit_WP[i][0], Clintar_spirit_WP[i][1], Clintar_spirit_WP[i][2], Clintar_spirit_WP[i][3], (uint32)Clintar_spirit_WP[i][4]);
}
PlayerGUID = player->GetGUID();
Start(true, false, PlayerGUID);
@@ -210,7 +210,7 @@ public:
void UpdateAI(uint32 diff) override
{
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (!PlayerGUID)
{
@@ -370,7 +370,7 @@ public:
} else if (EventOnWait) EventTimer -= diff;
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
CurrWP = waypointId;
EventTimer = 0;
diff --git a/src/server/scripts/Kalimdor/zone_orgrimmar.cpp b/src/server/scripts/Kalimdor/zone_orgrimmar.cpp
index 2603173e992..fc0d5120015 100644
--- a/src/server/scripts/Kalimdor/zone_orgrimmar.cpp
+++ b/src/server/scripts/Kalimdor/zone_orgrimmar.cpp
@@ -170,6 +170,11 @@ enum ThrallWarchief
SPELL_SHOCK = 16034
};
+enum Sounds
+{
+ SOUND_AGGRO = 5880
+};
+
/// @todo verify abilities/timers
class npc_thrall_warchief : public CreatureScript
{
@@ -197,7 +202,10 @@ public:
Initialize();
}
- void EnterCombat(Unit* /*who*/) override { }
+ void EnterCombat(Unit* /*who*/) override
+ {
+ DoPlaySoundToSet(me, SOUND_AGGRO);
+ }
void UpdateAI(uint32 diff) override
{
diff --git a/src/server/scripts/Kalimdor/zone_silithus.cpp b/src/server/scripts/Kalimdor/zone_silithus.cpp
index f5b6ebba946..2ac6d96b883 100644
--- a/src/server/scripts/Kalimdor/zone_silithus.cpp
+++ b/src/server/scripts/Kalimdor/zone_silithus.cpp
@@ -1226,13 +1226,13 @@ class go_wind_stone : public GameObjectScript
case NPC_DUKE_WATER:
case NPC_DUKE_EARTH:
case NPC_DUKE_AIR:
- summons->AI()->Talk(SAY_DUKE_AGGRO);
+ summons->AI()->Talk(SAY_DUKE_AGGRO, player);
break;
case NPC_ROYAL_FIRE:
case NPC_ROYAL_AIR:
case NPC_ROYAL_EARTH:
case NPC_ROYAL_WATER:
- summons->AI()->Talk(YELL_ROYAL_AGGRO);
+ summons->AI()->Talk(YELL_ROYAL_AGGRO, player);
break;
}
summons->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
diff --git a/src/server/scripts/Kalimdor/zone_stonetalon_mountains.cpp b/src/server/scripts/Kalimdor/zone_stonetalon_mountains.cpp
index fa9164fced8..9095ac29830 100644
--- a/src/server/scripts/Kalimdor/zone_stonetalon_mountains.cpp
+++ b/src/server/scripts/Kalimdor/zone_stonetalon_mountains.cpp
@@ -46,11 +46,11 @@ class npc_kaya_flathoof : public CreatureScript
public:
npc_kaya_flathoof() : CreatureScript("npc_kaya_flathoof") { }
- struct npc_kaya_flathoofAI : public npc_escortAI
+ struct npc_kaya_flathoofAI : public EscortAI
{
- npc_kaya_flathoofAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_kaya_flathoofAI(Creature* creature) : EscortAI(creature) { }
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
diff --git a/src/server/scripts/Kalimdor/zone_tanaris.cpp b/src/server/scripts/Kalimdor/zone_tanaris.cpp
index b1e44a4ac55..1898b9406b0 100644
--- a/src/server/scripts/Kalimdor/zone_tanaris.cpp
+++ b/src/server/scripts/Kalimdor/zone_tanaris.cpp
@@ -24,7 +24,6 @@ SDCategory: Tanaris
EndScriptData */
/* ContentData
-npc_aquementas
npc_custodian_of_time
npc_OOX17
npc_tooga
@@ -40,127 +39,6 @@ EndContentData */
#include "WorldSession.h"
/*######
-## npc_aquementas
-######*/
-
-enum Aquementas
-{
- AGGRO_YELL_AQUE = 0,
-
- SPELL_AQUA_JET = 13586,
- SPELL_FROST_SHOCK = 15089,
-
- ITEM_BOOK_OF_AQUOR = 11169,
- ITEM_SILVERY_CLAWS = 11172,
- ITEM_IRONTREE_HEART = 11173,
- ITEM_SILVER_TOTEM = 11522
-};
-
-class npc_aquementas : public CreatureScript
-{
-public:
- npc_aquementas() : CreatureScript("npc_aquementas") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_aquementasAI(creature);
- }
-
- struct npc_aquementasAI : public ScriptedAI
- {
- npc_aquementasAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- }
-
- void Initialize()
- {
- SendItemTimer = 0;
- SwitchFactionTimer = 10000;
-
- isFriendly = true;
-
- AquaJetTimer = 5000;
- FrostShockTimer = 1000;
- }
-
- uint32 SendItemTimer;
- uint32 SwitchFactionTimer;
- bool isFriendly;
-
- uint32 FrostShockTimer;
- uint32 AquaJetTimer;
-
- void Reset() override
- {
- Initialize();
- me->SetFaction(FACTION_FRIENDLY);
- }
-
- void SendItem(Unit* receiver)
- {
- Player* player = receiver->ToPlayer();
-
- if (player && player->HasItemCount(ITEM_BOOK_OF_AQUOR, 1, false) &&
- player->HasItemCount(ITEM_SILVERY_CLAWS, 11, false) &&
- player->HasItemCount(ITEM_IRONTREE_HEART, 1, false) &&
- !player->HasItemCount(ITEM_SILVER_TOTEM, 1, true))
- {
- ItemPosCountVec dest;
- uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 11522, 1, nullptr);
- if (msg == EQUIP_ERR_OK)
- player->StoreNewItem(dest, ITEM_SILVER_TOTEM, true);
- }
- }
-
- void EnterCombat(Unit* who) override
- {
- Talk(AGGRO_YELL_AQUE, who);
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (isFriendly)
- {
- if (SwitchFactionTimer <= diff)
- {
- me->SetFaction(FACTION_ELEMENTAL);
- isFriendly = false;
- } else SwitchFactionTimer -= diff;
- }
-
- if (!UpdateVictim())
- return;
-
- if (!isFriendly)
- {
- if (SendItemTimer <= diff)
- {
- if (me->GetVictim() && me->EnsureVictim()->GetTypeId() == TYPEID_PLAYER)
- SendItem(me->GetVictim());
- SendItemTimer = 5000;
- } else SendItemTimer -= diff;
- }
-
- if (FrostShockTimer <= diff)
- {
- DoCastVictim(SPELL_FROST_SHOCK);
- FrostShockTimer = 15000;
- } else FrostShockTimer -= diff;
-
- if (AquaJetTimer <= diff)
- {
- DoCast(me, SPELL_AQUA_JET);
- AquaJetTimer = 15000;
- } else AquaJetTimer -= diff;
-
- DoMeleeAttackIfReady();
- }
- };
-
-};
-
-/*######
## npc_custodian_of_time
######*/
@@ -195,11 +73,11 @@ public:
return new npc_custodian_of_timeAI(creature);
}
- struct npc_custodian_of_timeAI : public npc_escortAI
+ struct npc_custodian_of_timeAI : public EscortAI
{
- npc_custodian_of_timeAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_custodian_of_timeAI(Creature* creature) : EscortAI(creature) { }
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (Player* player = GetPlayerForEscort())
{
@@ -290,7 +168,7 @@ public:
void UpdateAI(uint32 diff) override
{
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
}
};
@@ -319,11 +197,11 @@ class npc_OOX17 : public CreatureScript
public:
npc_OOX17() : CreatureScript("npc_OOX17") { }
- struct npc_OOX17AI : public npc_escortAI
+ struct npc_OOX17AI : public EscortAI
{
- npc_OOX17AI(Creature* creature) : npc_escortAI(creature) { }
+ npc_OOX17AI(Creature* creature) : EscortAI(creature) { }
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (Player* player = GetPlayerForEscort())
{
@@ -551,7 +429,6 @@ public:
void AddSC_tanaris()
{
- new npc_aquementas();
new npc_custodian_of_time();
new npc_OOX17();
new npc_tooga();
diff --git a/src/server/scripts/Kalimdor/zone_the_barrens.cpp b/src/server/scripts/Kalimdor/zone_the_barrens.cpp
index 4e1c211ddde..2029ee3fbba 100644
--- a/src/server/scripts/Kalimdor/zone_the_barrens.cpp
+++ b/src/server/scripts/Kalimdor/zone_the_barrens.cpp
@@ -101,13 +101,13 @@ class npc_gilthares : public CreatureScript
public:
npc_gilthares() : CreatureScript("npc_gilthares") { }
- struct npc_giltharesAI : public npc_escortAI
+ struct npc_giltharesAI : public EscortAI
{
- npc_giltharesAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_giltharesAI(Creature* creature) : EscortAI(creature) { }
void Reset() override { }
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
@@ -530,9 +530,9 @@ class npc_wizzlecrank_shredder : public CreatureScript
public:
npc_wizzlecrank_shredder() : CreatureScript("npc_wizzlecrank_shredder") { }
- struct npc_wizzlecrank_shredderAI : public npc_escortAI
+ struct npc_wizzlecrank_shredderAI : public EscortAI
{
- npc_wizzlecrank_shredderAI(Creature* creature) : npc_escortAI(creature)
+ npc_wizzlecrank_shredderAI(Creature* creature) : EscortAI(creature)
{
IsPostEvent = false;
PostEventTimer = 1000;
@@ -556,7 +556,7 @@ public:
}
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -579,7 +579,7 @@ public:
}
}
- void WaypointStart(uint32 PointId) override
+ void WaypointStarted(uint32 PointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
diff --git a/src/server/scripts/Kalimdor/zone_thousand_needles.cpp b/src/server/scripts/Kalimdor/zone_thousand_needles.cpp
index a1439f4cc00..7823e535bb2 100644
--- a/src/server/scripts/Kalimdor/zone_thousand_needles.cpp
+++ b/src/server/scripts/Kalimdor/zone_thousand_needles.cpp
@@ -56,13 +56,13 @@ class npc_kanati : public CreatureScript
public:
npc_kanati() : CreatureScript("npc_kanati") { }
- struct npc_kanatiAI : public npc_escortAI
+ struct npc_kanatiAI : public EscortAI
{
- npc_kanatiAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_kanatiAI(Creature* creature) : EscortAI(creature) { }
void Reset() override { }
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -136,13 +136,13 @@ class npc_lakota_windsong : public CreatureScript
public:
npc_lakota_windsong() : CreatureScript("npc_lakota_windsong") { }
- struct npc_lakota_windsongAI : public npc_escortAI
+ struct npc_lakota_windsongAI : public EscortAI
{
- npc_lakota_windsongAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_lakota_windsongAI(Creature* creature) : EscortAI(creature) { }
void Reset() override { }
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -216,13 +216,13 @@ class npc_paoka_swiftmountain : public CreatureScript
public:
npc_paoka_swiftmountain() : CreatureScript("npc_paoka_swiftmountain") { }
- struct npc_paoka_swiftmountainAI : public npc_escortAI
+ struct npc_paoka_swiftmountainAI : public EscortAI
{
- npc_paoka_swiftmountainAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_paoka_swiftmountainAI(Creature* creature) : EscortAI(creature) { }
void Reset() override { }
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
diff --git a/src/server/scripts/Kalimdor/zone_thunder_bluff.cpp b/src/server/scripts/Kalimdor/zone_thunder_bluff.cpp
index 0f894631345..cca5311c8b8 100644
--- a/src/server/scripts/Kalimdor/zone_thunder_bluff.cpp
+++ b/src/server/scripts/Kalimdor/zone_thunder_bluff.cpp
@@ -41,6 +41,11 @@ enum CairneBloodhoof
SPELL_UPPERCUT = 22916
};
+enum Sounds
+{
+ SOUND_AGGRO = 5884
+};
+
#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
class npc_cairne_bloodhoof : public CreatureScript
@@ -75,7 +80,10 @@ public:
Initialize();
}
- void EnterCombat(Unit* /*who*/) override { }
+ void EnterCombat(Unit* /*who*/) override
+ {
+ DoPlaySoundToSet(me, SOUND_AGGRO);
+ }
void UpdateAI(uint32 diff) override
{
diff --git a/src/server/scripts/Kalimdor/zone_ungoro_crater.cpp b/src/server/scripts/Kalimdor/zone_ungoro_crater.cpp
index 4a1456a18c0..f7f7c5cd1dd 100644
--- a/src/server/scripts/Kalimdor/zone_ungoro_crater.cpp
+++ b/src/server/scripts/Kalimdor/zone_ungoro_crater.cpp
@@ -57,9 +57,9 @@ class npc_ame : public CreatureScript
public:
npc_ame() : CreatureScript("npc_ame") { }
- struct npc_ameAI : public npc_escortAI
+ struct npc_ameAI : public EscortAI
{
- npc_ameAI(Creature* creature) : npc_escortAI(creature)
+ npc_ameAI(Creature* creature) : EscortAI(creature)
{
Initialize();
}
@@ -71,7 +71,7 @@ public:
uint32 DemoralizingShoutTimer;
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (Player* player = GetPlayerForEscort())
{
@@ -118,7 +118,7 @@ public:
void UpdateAI(uint32 diff) override
{
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (!UpdateVictim())
return;
diff --git a/src/server/scripts/Kalimdor/zone_winterspring.cpp b/src/server/scripts/Kalimdor/zone_winterspring.cpp
index 9bc3711e830..5e7080ae621 100644
--- a/src/server/scripts/Kalimdor/zone_winterspring.cpp
+++ b/src/server/scripts/Kalimdor/zone_winterspring.cpp
@@ -19,12 +19,11 @@
/* ScriptData
SDName: Winterspring
SD%Complete: Almost Completely Emptied
-SDComment: Vendor Rivern Frostwind. Quest Support 4901
+SDComment: Quest Support 4901
SDCategory: Winterspring
EndScriptData */
/* ContentData
-npc_rivern_frostwind
npc_ranshalla
go_elune_fire
EndContentData */
@@ -36,52 +35,9 @@ EndContentData */
#include "ObjectAccessor.h"
#include "Player.h"
#include "ScriptedEscortAI.h"
-#include "ScriptedGossip.h"
#include "TemporarySummon.h"
#include "WorldSession.h"
-/*######
-## npc_rivern_frostwind
-######*/
-
-class npc_rivern_frostwind : public CreatureScript
-{
-public:
- npc_rivern_frostwind() : CreatureScript("npc_rivern_frostwind") { }
-
- struct npc_rivern_frostwindAI : public ScriptedAI
- {
- npc_rivern_frostwindAI(Creature* creature) : ScriptedAI(creature) { }
-
- bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
- {
- uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
- ClearGossipMenuFor(player);
- if (action == GOSSIP_ACTION_TRADE)
- player->GetSession()->SendListInventory(me->GetGUID());
-
- return true;
- }
-
- bool GossipHello(Player* player) override
- {
- if (me->IsQuestGiver())
- player->PrepareQuestMenu(me->GetGUID());
-
- if (me->IsVendor() && player->GetReputationRank(589) == REP_EXALTED)
- AddGossipItemFor(player, GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
-
- SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
- return true;
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_rivern_frostwindAI(creature);
- }
-};
-
enum Says
{
// Escort texts
@@ -307,9 +263,9 @@ class npc_ranshalla : public CreatureScript
public:
npc_ranshalla() : CreatureScript("npc_ranshalla") { }
- struct npc_ranshallaAI : public npc_escortAI, private DialogueHelper
+ struct npc_ranshallaAI : public EscortAI, private DialogueHelper
{
- npc_ranshallaAI(Creature* creature) : npc_escortAI(creature), DialogueHelper(introDialogue)
+ npc_ranshallaAI(Creature* creature) : EscortAI(creature), DialogueHelper(introDialogue)
{
Initialize();
}
@@ -393,7 +349,7 @@ public:
StartNextDialogueText(SAY_PRIESTESS_ALTAR_3);
}
- void WaypointReached(uint32 pointId) override
+ void WaypointReached(uint32 pointId, uint32 /*pathId*/) override
{
switch (pointId)
{
@@ -580,7 +536,7 @@ public:
if (events.ExecuteEvent() == EVENT_RESUME)
StartNextDialogueText(SAY_PRIESTESS_ALTAR_3);
- npc_escortAI::UpdateEscortAI(diff);
+ EscortAI::UpdateEscortAI(diff);
}
void QuestAccept(Player* player, Quest const* quest) override
@@ -643,7 +599,6 @@ public:
void AddSC_winterspring()
{
- new npc_rivern_frostwind();
new npc_ranshalla();
new go_elune_fire();
}
diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/ahnkahet.h b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/ahnkahet.h
index 00bd46ce2d5..ba70be7f02d 100644
--- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/ahnkahet.h
+++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/ahnkahet.h
@@ -37,13 +37,7 @@ enum AKDataTypes
// Additional Data
DATA_SPHERE_1 = 5,
DATA_SPHERE_2 = 6,
- DATA_PRINCE_TALDARAM_PLATFORM = 7,
- DATA_PL_JEDOGA_TARGET = 8,
- DATA_ADD_JEDOGA_OPFER = 9,
- DATA_ADD_JEDOGA_INITIAND = 10,
- DATA_JEDOGA_TRIGGER_SWITCH = 11,
- DATA_JEDOGA_RESET_INITIANDS = 12,
- DATA_ALL_INITIAND_DEAD = 13
+ DATA_PRINCE_TALDARAM_PLATFORM = 7
};
enum AKCreatureIds
@@ -59,7 +53,9 @@ enum AKCreatureIds
NPC_AHNKAHAR_SWARMER = 30178,
// Jedoga Shadowseeker
- NPC_INITIAND = 30114,
+ NPC_TWILIGHT_INITIATE = 30114,
+ NPC_TWILIGHT_VOLUNTEER = 30385,
+ NPC_TWILIGHT_WORSHIPPER = 30111,
NPC_JEDOGA_CONTROLLER = 30181,
// Amanitar
@@ -88,4 +84,6 @@ inline AI* GetAhnKahetAI(T* obj)
return GetInstanceAI<AI>(obj, AhnKahetScriptName);
}
+#define RegisterAhnKahetCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetAhnKahetAI)
+
#endif // AHNKAHET_H_
diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp
index f4881aaa9ed..514e8a44742 100644
--- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp
@@ -19,218 +19,266 @@
#include "ahnkahet.h"
#include "InstanceScript.h"
#include "ScriptedCreature.h"
-#include "TemporarySummon.h"
+#include "SpellScript.h"
-enum Spells
+enum AmanitarSpells
{
- 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
- SPELL_POWER_MUSHROOM_VISUAL_AURA = 56740,
+ //Amanitar
+ SPELL_BASH = 57094,
+ SPELL_ENTANGLING_ROOTS = 57095,
+ SPELL_MINI = 57055,
+ SPELL_VENOM_BOLT_VOLLEY = 57088,
+ SPELL_REMOVE_MUSHROOM_POWER = 57283,
+ //Mushrooms
+ SPELL_POTENT_FUNGUS = 56648,
+ SPELL_POISONOUS_MUSHROOM_POISON_CLOUD = 57061,
+ SPELL_POISONOUS_MUSHROOM_VISUAL_AURA = 56741,
+ SPELL_POWER_MUSHROOM_VISUAL_AURA = 56740,
+ SPELL_PUTRID_MUSHROOM = 31690,
+ SPELL_GROW = 57059,
+ SPELL_SHRINK = 31691
};
-enum Creatures
-{
- NPC_TRIGGER = 19656
-};
-
-enum Events
+enum AmanitarEvents
{
EVENT_SPAWN = 1,
EVENT_MINI,
EVENT_ROOT,
EVENT_BASH,
EVENT_BOLT,
- EVENT_AURA
+ EVENT_RESPAWN
};
-class boss_amanitar : public CreatureScript
+Position const MushroomPositions[32] =
{
- public:
- boss_amanitar() : CreatureScript("boss_amanitar") { }
+ { 373.4807f, -856.5301f, -74.30518f, 0.2094395f },
+ { 358.4792f, -879.3193f, -75.9463f, 5.166174f },
+ { 356.5531f, -846.3022f, -72.1796f, 3.193953f },
+ { 332.369f, -846.081f, -74.30516f, 4.834562f },
+ { 360.2234f, -862.055f, -75.22755f, 1.658063f },
+ { 351.7189f, -890.9619f, -76.54617f, 1.064651f },
+ { 345.8126f, -869.1772f, -77.17728f, 1.361357f },
+ { 367.5179f, -884.0129f, -77.32881f, 4.276057f },
+ { 370.6044f, -868.4305f, -74.19881f, 0.8901179f },
+ { 381.3156f, -873.2377f, -74.82656f, 1.099557f },
+ { 371.5869f, -873.8141f, -74.72424f, 1.082104f },
+ { 340.4079f, -891.6375f, -74.99128f, 1.134464f },
+ { 368.21f, -851.5953f, -73.99741f, 4.694936f },
+ { 328.7047f, -853.9812f, -75.51253f, 0.5759587f },
+ { 366.4145f, -876.39f, -75.52739f, 5.253441f },
+ { 380.1362f, -861.4344f, -73.45917f, 3.787364f },
+ { 373.3007f, -888.8057f, -79.03593f, 5.602507f },
+ { 348.3599f, -848.0839f, -73.54117f, 1.745329f },
+ { 352.5586f, -882.6624f, -75.68202f, 3.822271f },
+ { 357.8967f, -871.179f, -75.77553f, 2.443461f },
+ { 360.1034f, -842.3351f, -71.08852f, 4.34587f },
+ { 348.1334f, -861.5244f, -74.61307f, 2.565634f },
+ { 401.4896f, -866.7059f, -73.22395f, 0.8901179f },
+ { 360.1683f, -889.1515f, -76.74798f, 3.612832f },
+ { 350.1828f, -907.7313f, -74.94678f, 5.044002f },
+ { 340.6278f, -856.5973f, -74.23862f, 4.415683f },
+ { 366.4849f, -859.7621f, -74.82679f, 1.500983f },
+ { 359.1482f, -853.3346f, -74.47543f, 5.654867f },
+ { 374.9992f, -879.0921f, -75.56115f, 1.867502f },
+ { 339.5252f, -850.4612f, -74.45442f, 4.764749f },
+ { 337.0534f, -864.002f, -75.72749f, 4.642576f },
+ { 398.2797f, -851.8694f, -68.84419f, 0.5759587f }
+};
- struct boss_amanitarAI : public BossAI
- {
- boss_amanitarAI(Creature* creature) : BossAI(creature, DATA_AMANITAR) { }
+struct boss_amanitar : public BossAI
+{
+ boss_amanitar(Creature* creature) : BossAI(creature, DATA_AMANITAR) { }
- void Reset() override
- {
- _Reset();
- me->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE);
- me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true);
- }
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _EnterCombat();
+ events.ScheduleEvent(EVENT_ROOT, Seconds(5), Seconds(9));
+ events.ScheduleEvent(EVENT_BASH, Seconds(10), Seconds(14));
+ events.ScheduleEvent(EVENT_BOLT, Seconds(15), Seconds(20));
+ events.ScheduleEvent(EVENT_MINI, Seconds(12), Seconds(18));
+ events.ScheduleEvent(EVENT_SPAWN, Seconds(1));
+ events.ScheduleEvent(EVENT_RESPAWN, Seconds(40), Seconds(60));
+ }
- void EnterCombat(Unit* /*who*/) override
- {
- _EnterCombat();
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ _EnterEvadeMode();
+ summons.DespawnAll();
+ instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI);
+ _DespawnAtEvade();
+ }
- events.ScheduleEvent(EVENT_ROOT, urand(5, 9) * IN_MILLISECONDS);
- events.ScheduleEvent(EVENT_BASH, urand(10, 14) * IN_MILLISECONDS);
- events.ScheduleEvent(EVENT_BOLT, urand(15, 20) * IN_MILLISECONDS);
- events.ScheduleEvent(EVENT_MINI, urand(12, 18) * IN_MILLISECONDS);
- events.ScheduleEvent(EVENT_SPAWN, 5 * IN_MILLISECONDS);
- }
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ DoCastAOE(SPELL_REMOVE_MUSHROOM_POWER);
+ instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI);
+ }
- void JustDied(Unit* /*killer*/) override
- {
- _JustDied();
- instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI);
- }
+ void JustSummoned(Creature* summon) override
+ {
+ summons.Summon(summon);
+ }
- void SpawnAdds()
- {
- uint8 u = 0;
+ void SummonedCreatureDies(Creature* summon, Unit* killer) override
+ {
+ _mushroomsDeque.push_back(summon->GetPosition());
- for (uint8 i = 0; i < 30; ++i)
- {
- Position pos = me->GetRandomNearPosition(30.0f);
- me->UpdateGroundPositionZ(pos.GetPositionX(), pos.GetPositionY(), pos.m_positionZ);
+ BossAI::SummonedCreatureDies(summon, killer);
+ }
- if (Creature* trigger = me->SummonCreature(NPC_TRIGGER, pos))
- {
- Creature* temp1 = trigger->FindNearestCreature(NPC_HEALTHY_MUSHROOM, 4.0f, true);
- Creature* temp2 = trigger->FindNearestCreature(NPC_POISONOUS_MUSHROOM, 4.0f, true);
- if (!temp1 && !temp2)
- {
- u = 1 - u;
- me->SummonCreature(u > 0 ? NPC_POISONOUS_MUSHROOM : NPC_HEALTHY_MUSHROOM, pos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60 * IN_MILLISECONDS);
- }
- trigger->DespawnOrUnsummon();
- }
- }
- }
+ void SpawnMushroom(Position const pos)
+ {
+ me->SummonCreature(roll_chance_i(40) ? NPC_HEALTHY_MUSHROOM : NPC_POISONOUS_MUSHROOM, pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 4000);
+ }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- events.Update(diff);
+ events.Update(diff);
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SPAWN:
+ for (Position const pos : MushroomPositions)
+ SpawnMushroom(pos);
+ break;
+ case EVENT_MINI:
+ if (SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, true, -SPELL_MINI))
{
- case EVENT_SPAWN:
- SpawnAdds();
- events.ScheduleEvent(EVENT_SPAWN, 20 * IN_MILLISECONDS);
- break;
- case EVENT_MINI:
- DoCast(SPELL_MINI);
- events.ScheduleEvent(EVENT_MINI, urand(25, 30) * IN_MILLISECONDS);
- break;
- case EVENT_ROOT:
- DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_ENTANGLING_ROOTS, true);
- events.ScheduleEvent(EVENT_ROOT, urand(10, 15) * IN_MILLISECONDS);
- break;
- case EVENT_BASH:
- DoCastVictim(SPELL_BASH);
- events.ScheduleEvent(EVENT_BASH, urand(7, 12) * IN_MILLISECONDS);
- break;
- case EVENT_BOLT:
- DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_VENOM_BOLT_VOLLEY, true);
- events.ScheduleEvent(EVENT_BOLT, urand(18, 22) * IN_MILLISECONDS);
- break;
- default:
- break;
+ DoCastAOE(SPELL_MINI);
+ events.Repeat(Seconds(30));
}
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- }
- DoMeleeAttackIfReady();
+ else
+ events.Repeat(Seconds(1));
+ break;
+ case EVENT_ROOT:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true))
+ DoCast(target, SPELL_ENTANGLING_ROOTS, true);
+ events.Repeat(Seconds(10), Seconds(15));
+ break;
+ case EVENT_BASH:
+ DoCastVictim(SPELL_BASH);
+ events.Repeat(Seconds(7), Seconds(12));
+ break;
+ case EVENT_BOLT:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ DoCast(target, SPELL_VENOM_BOLT_VOLLEY, true);
+ events.Repeat(Seconds(18), Seconds(22));
+ break;
+ case EVENT_RESPAWN:
+ while (!_mushroomsDeque.empty())
+ {
+ SpawnMushroom(_mushroomsDeque.front());
+ _mushroomsDeque.pop_front();
+ }
+ events.Repeat(Seconds(40), Seconds(60));
+ break;
+ default:
+ break;
}
- };
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetAhnKahetAI<boss_amanitarAI>(creature);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ std::deque<Position> _mushroomsDeque;
};
-class npc_amanitar_mushrooms : public CreatureScript
+struct npc_amanitar_mushrooms : public ScriptedAI
{
-public:
- npc_amanitar_mushrooms() : CreatureScript("npc_amanitar_mushrooms") { }
+ npc_amanitar_mushrooms(Creature* creature) : ScriptedAI(creature), _active(false) { }
- struct npc_amanitar_mushroomsAI : public ScriptedAI
+ void Reset() override
{
- npc_amanitar_mushroomsAI(Creature* creature) : ScriptedAI(creature) { }
+ me->SetReactState(REACT_PASSIVE);
+ me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
+ DoCastSelf(SPELL_PUTRID_MUSHROOM);
+ DoCastSelf(SPELL_SHRINK, true);
+ DoCastSelf(SPELL_GROW, true);
- EventMap events;
+ if (me->GetEntry() == NPC_HEALTHY_MUSHROOM)
+ {
+ DoCastSelf(SPELL_POWER_MUSHROOM_VISUAL_AURA);
+ _active = true;
+ }
+ else
+ DoCastSelf(SPELL_POISONOUS_MUSHROOM_VISUAL_AURA);
- void Reset() override
+ _scheduler.Schedule(Milliseconds(800), [this](TaskContext /*context*/)
{
- events.Reset();
- events.ScheduleEvent(EVENT_AURA, 1 * IN_MILLISECONDS);
+ DoCastSelf(SPELL_GROW, true);
+ });
+ }
+
+ void MoveInLineOfSight(Unit* target) override
+ {
+ if (_active || target->GetTypeId() != TYPEID_PLAYER || me->GetDistance2d(target) > 2.0f)
+ return;
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
- DoCast(SPELL_PUTRID_MUSHROOM);
+ _active = true;
- if (me->GetEntry() == NPC_POISONOUS_MUSHROOM)
- DoCast(SPELL_POISONOUS_MUSHROOM_VISUAL_AURA);
- else
- DoCast(SPELL_POWER_MUSHROOM_VISUAL_AURA);
- }
+ target->RemoveAurasDueToSpell(SPELL_POTENT_FUNGUS);
+ DoCastAOE(SPELL_POISONOUS_MUSHROOM_POISON_CLOUD);
- void DamageTaken(Unit* /*attacker*/, uint32 &damage) override
+ _scheduler.Schedule(Seconds(1), [this](TaskContext /*context*/)
{
- if (damage >= me->GetHealth() && me->GetEntry() == NPC_HEALTHY_MUSHROOM)
- DoCast(me, SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS, true);
- }
+ me->SetObjectScale(0.1f);
+ me->DespawnOrUnsummon(Seconds(4));
+ });
+ }
- void EnterCombat(Unit* /*who*/) override { }
- void AttackStart(Unit* /*victim*/) override { }
+ void JustDied(Unit* /*killer*/) override
+ {
+ if (me->GetEntry() == NPC_HEALTHY_MUSHROOM)
+ DoCastAOE(SPELL_POTENT_FUNGUS, true);
+ }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ void UpdateAI(uint32 diff) override
+ {
+ _scheduler.Update(diff);
+ }
- events.Update(diff);
+private:
+ TaskScheduler _scheduler;
+ bool _active;
+};
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+// 56648 - Potent Fungus
+class spell_amanitar_potent_fungus : public AuraScript
+{
+ PrepareAuraScript(spell_amanitar_potent_fungus);
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_AURA:
- if (me->GetEntry() == NPC_POISONOUS_MUSHROOM)
- {
- DoCast(me, SPELL_POISONOUS_MUSHROOM_VISUAL_AREA, true);
- DoCast(me, SPELL_POISONOUS_MUSHROOM_POISON_CLOUD);
- }
- events.ScheduleEvent(EVENT_AURA, 7 * IN_MILLISECONDS);
- break;
- default:
- break;
- }
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- }
- }
- };
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* target = GetTarget();
+ if (!target->HasAura(SPELL_MINI))
+ return;
+
+ target->RemoveAurasDueToSpell(SPELL_MINI);
+ Remove();
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void Register() override
{
- return GetAhnKahetAI<npc_amanitar_mushroomsAI>(creature);
+ AfterEffectApply += AuraEffectApplyFn(spell_amanitar_potent_fungus::OnApply, EFFECT_0, SPELL_AURA_MOD_SCALE, AURA_EFFECT_HANDLE_REAL);
}
};
void AddSC_boss_amanitar()
{
- new boss_amanitar();
- new npc_amanitar_mushrooms();
+ RegisterAhnKahetCreatureAI(boss_amanitar);
+ RegisterAhnKahetCreatureAI(npc_amanitar_mushrooms);
+ RegisterAuraScript(spell_amanitar_potent_fungus);
}
diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp
index 882b3c22410..7ab94f69186 100644
--- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp
@@ -15,589 +15,484 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/*
- * Comment: Visuals missing, de-germanize code, wow 3.3.5a-ize
- * Patch 3.3.2 (2010-01-02): Jedoga Shadowseeker now only ascends once during the encounter.
- */
-
#include "ScriptMgr.h"
#include "ahnkahet.h"
#include "InstanceScript.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "ScriptedCreature.h"
+#include "Spell.h"
+#include "SpellScript.h"
+#include "TemporarySummon.h"
enum Yells
{
- TEXT_AGGRO = 0,
- TEXT_SACRIFICE_1 = 1,
- TEXT_SACRIFICE_2 = 2,
- TEXT_SLAY = 3,
- TEXT_DEATH = 4,
- TEXT_PREACHING = 5
+ SAY_AGGRO = 0,
+ SAY_CHOOSE = 1,
+ SAY_SACRIFICE = 2,
+ SAY_SLAY = 3,
+ SAY_DEATH = 4,
+ SAY_PREACHING = 5,
+
+ SAY_CHOSEN = 0,
+ SAY_SACRIFICED = 1
};
-enum Spells
+enum JedogaSpells
{
- SPELL_SPHERE_VISUAL = 56075,
- SPELL_GIFT_OF_THE_HERALD = 56219,
- SPELL_CYCLONE_STRIKE = 56855, // Self
- SPELL_LIGHTNING_BOLT = 56891, // 40Y
- SPELL_THUNDERSHOCK = 56926 // 30Y
+ SPELL_RANDOM_LIGHTNING_VISUAL = 56327,
+ SPELL_HOVER_FALL_1 = 56100,
+ SPELL_HOVER_FALL_2 = 56157,
+ SPELL_SPHERE_VISUAL = 56075,
+ SPELL_LIGHTNING_BOLT = 56891,
+ SPELL_THUNDERSHOCK = 56926,
+ SPELL_CYCLONE_STRIKE = 56855,
+ SPELL_SACRIFICE_BEAM = 56150,
+
+ //Jedoga Controller
+ SPELL_BEAM_VISUAL_JEDOGA = 56312,
+ SPELL_SACRIFICE_VISUAL = 56133,
+
+ //Twilight Volunteer
+ SPELL_SPHERE_VISUAL_VOLUNTEER = 56102,
+ SPELL_PILLAR_OF_LIGHTNING = 56868
};
-const Position JedogaPosition[2] =
+enum JedogaEvents
{
- {372.330994f, -705.278015f, -0.624178f, 5.427970f},
- {372.330994f, -705.278015f, -16.179716f, 5.427970f}
+ EVENT_INTRO_SAY = 1,
+ EVENT_START_FIGHT_1,
+ EVENT_START_FIGHT_2,
+ EVENT_CYCLONE_STRIKE,
+ EVENT_LIGHTNING_BOLT,
+ EVENT_THUNDERSHOCK,
+ EVENT_START_PHASE_TWO,
+ EVENT_FLY_DELAY,
+ EVENT_END_PHASE_TWO,
+ EVENT_CHOOSE_VOLUNTEER,
+ EVENT_SUMMON_VOLUNTEER
};
-enum Misc
+enum JedogaPhases
{
- ACTION_INITIAND_KILLED = 1,
- DATA_VOLUNTEER_WORK = 2
+ PHASE_INTRO = 0,
+ PHASE_ONE,
+ PHASE_TWO,
+ PHASE_THREE
};
-class boss_jedoga_shadowseeker : public CreatureScript
+enum JedogaPoints
{
-public:
- boss_jedoga_shadowseeker() : CreatureScript("boss_jedoga_shadowseeker") { }
-
- struct boss_jedoga_shadowseekerAI : public ScriptedAI
- {
- boss_jedoga_shadowseekerAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- instance = creature->GetInstanceScript();
- bFirstTime = true;
- bPreDone = false;
- }
-
- void Initialize()
- {
- uiOpFerTimer = urand(15 * IN_MILLISECONDS, 20 * IN_MILLISECONDS);
+ POINT_INITIAL_POSITION = 0,
+ POINT_SACRIFICE,
+ POINT_GROUND,
+ POINT_PHASE_TWO,
+ POINT_PHASE_TWO_FLY
+};
- uiCycloneTimer = 3 * IN_MILLISECONDS;
- uiBoltTimer = 7 * IN_MILLISECONDS;
- uiThunderTimer = 12 * IN_MILLISECONDS;
+Position const SacrificePosition = { 376.5385f, -707.3567f, -16.14124f };
+Position const JedogaGroundPosition = { 371.6281f, -704.4836f, -16.17967f };
+Position const JedogaFlyPosition = { 371.627f, -704.4217f, -6.707521f };
+Position const JedogaControllerPositions[3] =
+{
+ { 402.7893f, -748.5251f, 29.39399f, 2.024582f },
+ { 420.1999f, -727.0132f, 28.88036f, 2.042035f },
+ { 375.4977f, -707.3635f, -16.0964f, 2.426008f }
+};
- bOpFerok = false;
- bOpFerokFail = false;
- bOnGround = false;
- bCanDown = false;
- volunteerWork = true;
- }
+typedef std::pair<Position, Position> VolunteerPositionPair;
+std::vector<VolunteerPositionPair> const VolunteerSpotPositions =
+{
+ { { 400.7701f, -784.8928f, -31.60143f }, { 365.9514f, -719.1235f, -16.17974f } },
+ { { 397.3595f, -788.5157f, -31.59679f }, { 359.7433f, -715.017f, -16.17974f } },
+ { { 399.3177f, -787.2599f, -31.59631f }, { 362.0263f, -719.1036f, -16.17974f } },
+ { { 460.4623f, -719.2227f, -31.58718f }, { 389.266f, -679.3693f, -16.17973f } },
+ { { 456.0909f, -724.3412f, -31.58718f }, { 400.5992f, -691.7954f, -16.17973f } },
+ { { 452.6613f, -726.9518f, -31.58718f }, { 400.3423f, -701.5115f, -16.17974f } },
+ { { 447.8852f, -732.3298f, -31.58718f }, { 389.861f, -710.6993f, -16.17974f } },
+ { { 457.562f, -721.1855f, -31.58718f }, { 395.4494f, -684.5345f, -16.17973f } },
+ { { 451.7243f, -730.2181f, -31.58718f }, { 397.0945f, -708.4188f, -15.99747f } },
+ { { 413.9582f, -777.132f, -31.58716f }, { 388.1394f, -723.124f, -15.9938f } },
+ { { 411.5661f, -781.2356f, -31.58716f }, { 381.7102f, -730.0745f, -15.99554f } },
+ { { 407.395f, -786.793f, -31.58716f }, { 366.9791f, -737.3303f, -16.17974f } },
+ { { 404.9166f, -788.3472f, -31.58716f }, { 358.6124f, -735.9944f, -15.9855f } },
+ { { 401.5697f, -791.2033f, -31.58717f }, { 351.9383f, -729.6436f, -16.17974f } },
+ { { 410.1105f, -785.4691f, -31.58716f }, { 373.1659f, -736.2893f, -16.17974f } },
+ { { 442.5644f, -730.2499f, -31.59826f }, { 390.5955f, -714.6851f, -16.17974f } },
+ { { 445.5233f, -725.9542f, -31.60173f }, { 393.9694f, -708.1727f, -16.17974f } },
+ { { 448.5531f, -722.5888f, -31.60066f }, { 395.2702f, -702.556f, -16.17974f } },
+ { { 449.8521f, -719.7265f, -31.58849f }, { 394.5757f, -695.1004f, -16.17974f } },
+ { { 453.5134f, -717.7018f, -31.59883f }, { 387.6152f, -690.1782f, -16.17974f } },
+ { { 457.8564f, -711.7424f, -31.59773f }, { 378.6874f, -687.1343f, -16.17973f } },
+ { { 410.0583f, -774.4119f, -31.60115f }, { 383.8151f, -723.4276f, -16.17974f } },
+ { { 408.7458f, -777.955f, -31.59873f }, { 376.9857f, -725.0735f, -16.17974f } },
+ { { 405.2404f, -779.6614f, -31.60512f }, { 373.3736f, -722.7498f, -16.17974f } },
+ { { 404.0797f, -783.829f, -31.59497f }, { 367.8631f, -722.5212f, -16.17974f } }
+};
- InstanceScript* instance;
+enum JedogaMisc
+{
+ SUMMON_GROUP_INITIATES = 1,
+ SUMMON_GROUP_WORSHIPPERS = 2,
+ DATA_VOLUNTEER_WORK = 1,
+ ACTION_CHOSEN = 1,
+ ACTION_SACRIFICE = 2,
+ TWILIGHT_INITIATES_SIZE = 15
+};
- uint32 uiOpFerTimer;
- uint32 uiCycloneTimer;
- uint32 uiBoltTimer;
- uint32 uiThunderTimer;
+struct boss_jedoga_shadowseeker : public BossAI
+{
+ boss_jedoga_shadowseeker(Creature* creature) : BossAI(creature, DATA_JEDOGA_SHADOWSEEKER), _initiatesKilled(0), _volunteerWork(true) { }
- bool bPreDone;
- bool bOpFerok;
- bool bOnGround;
- bool bOpFerokFail;
- bool bCanDown;
- bool volunteerWork;
- bool bFirstTime;
+ void Reset() override
+ {
+ _Reset();
+ events.SetPhase(PHASE_INTRO);
+ me->SetReactState(REACT_PASSIVE);
+ me->SummonCreatureGroup(SUMMON_GROUP_INITIATES);
- void Reset() override
- {
- Initialize();
+ if (TempSummon* controller = me->SummonCreature(NPC_JEDOGA_CONTROLLER, JedogaControllerPositions[0], TEMPSUMMON_MANUAL_DESPAWN))
+ controller->CastSpell(me, SPELL_BEAM_VISUAL_JEDOGA);
+ if (TempSummon* controller = me->SummonCreature(NPC_JEDOGA_CONTROLLER, JedogaControllerPositions[1], TEMPSUMMON_MANUAL_DESPAWN))
+ controller->CastSpell(me, SPELL_BEAM_VISUAL_JEDOGA);
- if (!bFirstTime)
- instance->SetBossState(DATA_JEDOGA_SHADOWSEEKER, FAIL);
+ events.ScheduleEvent(EVENT_INTRO_SAY, Minutes(2), 0, PHASE_INTRO);
+ }
- instance->SetGuidData(DATA_PL_JEDOGA_TARGET, ObjectGuid::Empty);
- instance->SetGuidData(DATA_ADD_JEDOGA_OPFER, ObjectGuid::Empty);
- instance->SetData(DATA_JEDOGA_RESET_INITIANDS, 0);
- MoveUp();
+ void EnterCombat(Unit* /*who*/) override
+ {
+ me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL);
+ me->RemoveAurasDueToSpell(SPELL_RANDOM_LIGHTNING_VISUAL);
+ me->SummonCreatureGroup(SUMMON_GROUP_WORSHIPPERS);
- bFirstTime = false;
- }
+ _EnterCombat();
+ Talk(SAY_AGGRO);
+ events.SetPhase(PHASE_ONE);
- void EnterCombat(Unit* who) override
+ for (VolunteerPositionPair posPair : VolunteerSpotPositions)
{
- if (!instance || (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_JEDOGA_CONTROLLER))
- return;
-
- Talk(TEXT_AGGRO);
- me->SetInCombatWithZone();
- instance->SetBossState(DATA_JEDOGA_SHADOWSEEKER, IN_PROGRESS);
+ if (TempSummon* volunteer = me->SummonCreature(NPC_TWILIGHT_VOLUNTEER, posPair.first, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000))
+ {
+ volunteer->GetMotionMaster()->MovePoint(POINT_INITIAL_POSITION, posPair.second);
+ _volunteerGUIDS.push_back(volunteer->GetGUID());
+ }
}
+ }
- void AttackStart(Unit* who) override
- {
- if (!who || (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_JEDOGA_CONTROLLER))
- return;
-
- ScriptedAI::AttackStart(who);
- }
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ summons.DespawnAll();
+ _EnterEvadeMode();
+ _DespawnAtEvade(Seconds(15));
+ }
- void KilledUnit(Unit* Victim) override
- {
- if (!Victim || Victim->GetTypeId() != TYPEID_PLAYER)
- return;
+ void KilledUnit(Unit* Victim) override
+ {
+ if (Victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SLAY);
+ }
- Talk(TEXT_SLAY);
- }
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ Talk(SAY_DEATH);
+ }
- void JustDied(Unit* /*killer*/) override
- {
- Talk(TEXT_DEATH);
- instance->SetBossState(DATA_JEDOGA_SHADOWSEEKER, DONE);
- }
+ uint32 GetData(uint32 type) const override
+ {
+ if (type == DATA_VOLUNTEER_WORK)
+ return _volunteerWork ? 1 : 0;
- void DoAction(int32 action) override
- {
- if (action == ACTION_INITIAND_KILLED)
- volunteerWork = false;
- }
+ return 0;
+ }
- uint32 GetData(uint32 type) const override
+ void DamageTaken(Unit* /*done_by*/, uint32& /*damage*/) override
+ {
+ if (HealthBelowPct(55) && events.IsInPhase(PHASE_ONE))
{
- if (type == DATA_VOLUNTEER_WORK)
- return volunteerWork ? 1 : 0;
-
- return 0;
+ events.Reset();
+ events.SetPhase(PHASE_TWO);
+ events.ScheduleEvent(EVENT_START_PHASE_TWO, Seconds(1));
}
+ }
- void MoveInLineOfSight(Unit* who) override
+ void DoAction(int32 action) override
+ {
+ if (action == ACTION_SACRIFICE)
{
- if (!instance || !who || (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_JEDOGA_CONTROLLER))
- return;
-
- if (!bPreDone && who->GetTypeId() == TYPEID_PLAYER && me->GetDistance(who) < 100.0f)
- {
- Talk(TEXT_PREACHING);
- bPreDone = true;
- }
-
- if (instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) != IN_PROGRESS || !bOnGround)
- return;
-
- if (!me->GetVictim() && me->CanCreatureAttack(who))
- {
- 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
- {
- who->SetInCombatWith(me);
- AddThreat(who, 0.0f);
- }
- }
- }
+ Talk(SAY_SACRIFICE);
+ DoCastAOE(SPELL_SACRIFICE_BEAM);
+ events.ScheduleEvent(EVENT_END_PHASE_TWO, Seconds(3));
+ events.RescheduleEvent(EVENT_SUMMON_VOLUNTEER, Seconds(15));
}
+ }
- void MoveDown()
+ void JustSummoned(Creature* summon) override
+ {
+ if (summon->GetEntry() == NPC_TWILIGHT_WORSHIPPER)
{
- bOpFerokFail = false;
-
- instance->SetData(DATA_JEDOGA_TRIGGER_SWITCH, 0);
- me->GetMotionMaster()->MovePoint(1, JedogaPosition[1]);
- 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* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_PL_JEDOGA_TARGET)))
- {
- AttackStart(target);
- instance->SetData(DATA_JEDOGA_RESET_INITIANDS, 0);
- if (instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) != IN_PROGRESS)
- EnterCombat(target);
- }
- else if (!me->IsInCombat())
- EnterEvadeMode();
- }
+ summon->SetStandState(UNIT_STAND_STATE_KNEEL);
+ summons.Summon(summon);
+ return;
}
- void MoveUp()
- {
- 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]);
-
- instance->SetData(DATA_JEDOGA_TRIGGER_SWITCH, 1);
- if (instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) == IN_PROGRESS)
- OpferRufen();
-
- bOnGround = false;
- uiOpFerTimer = urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS);
- }
+ BossAI::JustSummoned(summon);
+ }
- void OpferRufen()
+ void SummonedCreatureDies(Creature* summon, Unit* killer) override
+ {
+ if (summon->GetEntry() == NPC_TWILIGHT_INITIATE)
{
- ObjectGuid opfer = instance->GetGuidData(DATA_ADD_JEDOGA_INITIAND);
-
- if (opfer)
+ if (++_initiatesKilled == TWILIGHT_INITIATES_SIZE)
{
- Talk(TEXT_SACRIFICE_1);
- instance->SetGuidData(DATA_ADD_JEDOGA_OPFER, opfer);
+ DoCastSelf(SPELL_HOVER_FALL_1);
+ me->RemoveByteFlag(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
+ events.ScheduleEvent(EVENT_START_FIGHT_1, Seconds(1));
}
- else
- bCanDown = true;
}
-
- void Opfern()
+ else if (summon->GetEntry() == NPC_TWILIGHT_VOLUNTEER)
{
- Talk(TEXT_SACRIFICE_2);
-
- me->InterruptNonMeleeSpells(false);
- DoCast(me, SPELL_GIFT_OF_THE_HERALD, false);
-
- bOpFerok = false;
- bCanDown = true;
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) != IN_PROGRESS && instance->GetData(DATA_ALL_INITIAND_DEAD))
- MoveDown();
-
- if (bOpFerok && !bOnGround && !bCanDown) Opfern();
+ _volunteerWork = false;
- if (bOpFerokFail && !bOnGround && !bCanDown)
- bCanDown = true;
-
- if (bCanDown)
+ if (events.IsInPhase(PHASE_TWO))
{
- MoveDown();
- bCanDown = false;
+ events.SetPhase(PHASE_THREE);
+ events.RescheduleEvent(EVENT_END_PHASE_TWO, Seconds(1));
}
- if (bOnGround)
- {
- if (!UpdateVictim())
- return;
-
- if (uiCycloneTimer <= diff)
- {
- DoCast(me, SPELL_CYCLONE_STRIKE, false);
- uiCycloneTimer = urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS);
- } else uiCycloneTimer -= diff;
-
- if (uiBoltTimer <= diff)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
- me->CastSpell(target, SPELL_LIGHTNING_BOLT, false);
-
- uiBoltTimer = urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS);
- } else uiBoltTimer -= diff;
-
- if (uiThunderTimer <= diff)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
- me->CastSpell(target, SPELL_THUNDERSHOCK, false);
-
- uiThunderTimer = urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS);
- } else uiThunderTimer -= diff;
-
- if (uiOpFerTimer <= diff)
- MoveUp();
- else
- uiOpFerTimer -= diff;
-
- DoMeleeAttackIfReady();
- }
+ events.RescheduleEvent(EVENT_SUMMON_VOLUNTEER, Seconds(10));
}
- };
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetAhnKahetAI<boss_jedoga_shadowseekerAI>(creature);
+ BossAI::SummonedCreatureDies(summon, killer);
}
-};
-
-class npc_jedoga_initiand : public CreatureScript
-{
-public:
- npc_jedoga_initiand() : CreatureScript("npc_jedoga_initiand") { }
- struct npc_jedoga_initiandAI : public ScriptedAI
+ void MovementInform(uint32 type, uint32 pointId) override
{
- npc_jedoga_initiandAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- instance = creature->GetInstanceScript();
- }
+ if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE)
+ return;
- void Initialize()
+ switch (pointId)
{
- bWalking = false;
- bCheckTimer = 2 * IN_MILLISECONDS;
+ case POINT_GROUND:
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->SetReactState(REACT_AGGRESSIVE);
+ DoZoneInCombat();
+ events.ScheduleEvent(EVENT_CYCLONE_STRIKE, Seconds(3));
+ events.ScheduleEvent(EVENT_LIGHTNING_BOLT, Seconds(7));
+ events.ScheduleEvent(EVENT_THUNDERSHOCK, Seconds(12));
+ break;
+ case POINT_PHASE_TWO:
+ events.ScheduleEvent(EVENT_FLY_DELAY, Seconds(2));
+ break;
+ case POINT_PHASE_TWO_FLY:
+ events.ScheduleEvent(EVENT_CHOOSE_VOLUNTEER, Seconds(2));
+ break;
+ default:
+ break;
}
+ }
- InstanceScript* instance;
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO))
+ return;
- uint32 bCheckTimer;
+ events.Update(diff);
- bool bWalking;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- void Reset() override
+ while (uint32 eventId = events.ExecuteEvent())
{
- Initialize();
-
- if (instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) != 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
+ switch (eventId)
{
- 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);
- }
- }
+ case EVENT_INTRO_SAY:
+ if (instance->GetBossState(DATA_PRINCE_TALDARAM) == DONE)
+ Talk(SAY_PREACHING);
+ events.Repeat(Minutes(2));
+ break;
+ case EVENT_START_FIGHT_1:
+ me->RemoveAurasDueToSpell(SPELL_BEAM_VISUAL_JEDOGA);
+ events.ScheduleEvent(EVENT_START_FIGHT_2, Seconds(1));
+ break;
+ case EVENT_START_FIGHT_2:
+ summons.DespawnEntry(NPC_JEDOGA_CONTROLLER);
+ me->SetDisableGravity(false);
+ me->RemoveByteFlag(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
+ me->GetMotionMaster()->MoveLand(POINT_GROUND, JedogaGroundPosition);
+ break;
+ case EVENT_START_PHASE_TWO:
+ me->SetReactState(REACT_PASSIVE);
+ me->AttackStop();
+ me->InterruptNonMeleeSpells(true);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->GetMotionMaster()->MovePoint(POINT_PHASE_TWO, JedogaGroundPosition);
+ break;
+ case EVENT_FLY_DELAY:
+ me->SetDisableGravity(true);
+ me->SetByteFlag(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
+ me->GetMotionMaster()->MoveTakeoff(POINT_PHASE_TWO_FLY, JedogaFlyPosition);
+ break;
+ case EVENT_CHOOSE_VOLUNTEER:
+ if (TempSummon* controller = me->SummonCreature(NPC_JEDOGA_CONTROLLER, JedogaControllerPositions[2], TEMPSUMMON_MANUAL_DESPAWN))
+ {
+ me->SetFacingToObject(controller);
+ controller->CastSpell(controller, SPELL_SACRIFICE_VISUAL);
+ }
- void JustDied(Unit* killer) override
- {
- if (!killer || !instance)
- return;
+ Talk(SAY_CHOOSE);
- if (bWalking)
- {
- if (Creature* boss = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_JEDOGA_SHADOWSEEKER)))
- {
- if (!ENSURE_AI(boss_jedoga_shadowseeker::boss_jedoga_shadowseekerAI, boss->AI())->bOpFerok)
- ENSURE_AI(boss_jedoga_shadowseeker::boss_jedoga_shadowseekerAI, boss->AI())->bOpFerokFail = true;
+ if (_volunteerGUIDS.empty())
+ break;
- if (killer->GetTypeId() == TYPEID_PLAYER)
- boss->AI()->DoAction(ACTION_INITIAND_KILLED);
+ _selectedVolunteerGUID = Trinity::Containers::SelectRandomContainerElement(_volunteerGUIDS);
+ if (Creature* volunteer = ObjectAccessor::GetCreature(*me, _selectedVolunteerGUID))
+ volunteer->AI()->DoAction(ACTION_CHOSEN);
+ break;
+ case EVENT_SUMMON_VOLUNTEER:
+ {
+ uint32 pos = std::distance(_volunteerGUIDS.begin(), std::find(_volunteerGUIDS.begin(), _volunteerGUIDS.end(), _selectedVolunteerGUID));
+ if (pos < VolunteerSpotPositions.size())
+ {
+ VolunteerPositionPair posPair = VolunteerSpotPositions.at(pos);
+ if (TempSummon* volunteer = me->SummonCreature(NPC_TWILIGHT_VOLUNTEER, posPair.first, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000))
+ volunteer->GetMotionMaster()->MovePoint(POINT_INITIAL_POSITION, posPair.second);
+ }
+ break;
}
-
- instance->SetGuidData(DATA_ADD_JEDOGA_OPFER, ObjectGuid::Empty);
-
- bWalking = false;
+ case EVENT_END_PHASE_TWO:
+ summons.DespawnEntry(NPC_JEDOGA_CONTROLLER);
+ DoCastSelf(SPELL_HOVER_FALL_2);
+ me->SetDisableGravity(false);
+ me->RemoveByteFlag(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
+ me->GetMotionMaster()->MoveLand(POINT_GROUND, JedogaGroundPosition);
+ break;
+ case EVENT_CYCLONE_STRIKE:
+ DoCastSelf(SPELL_CYCLONE_STRIKE);
+ events.Repeat(Seconds(15), Seconds(30));
+ break;
+ case EVENT_LIGHTNING_BOLT:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ DoCast(target, SPELL_LIGHTNING_BOLT);
+ events.Repeat(Seconds(15), Seconds(30));
+ break;
+ case EVENT_THUNDERSHOCK:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ DoCast(target, SPELL_THUNDERSHOCK);
+ events.Repeat(Seconds(15), Seconds(30));
+ break;
+ default:
+ break;
}
- if (killer->GetTypeId() == TYPEID_PLAYER)
- instance->SetGuidData(DATA_PL_JEDOGA_TARGET, killer->GetGUID());
- }
-
- void EnterCombat(Unit* /*who*/) override
- {
- }
- void AttackStart(Unit* victim) override
- {
- if ((instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) == IN_PROGRESS) || !victim)
+ if (me->HasUnitState(UNIT_STATE_CASTING))
return;
-
- ScriptedAI::AttackStart(victim);
}
- void MoveInLineOfSight(Unit* who) override
+ DoMeleeAttackIfReady();
+ }
- {
- if ((instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) == IN_PROGRESS) || !who)
- return;
+private:
+ uint8 _initiatesKilled;
+ bool _volunteerWork;
+ GuidVector _volunteerGUIDS;
+ ObjectGuid _selectedVolunteerGUID;
+};
- ScriptedAI::MoveInLineOfSight(who);
- }
+struct npc_twilight_volunteer : public ScriptedAI
+{
+ npc_twilight_volunteer(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript())
+ {
+ me->SetReactState(REACT_PASSIVE);
+ }
- void MovementInform(uint32 uiType, uint32 uiPointId) override
+ void DoAction(int32 action) override
+ {
+ if (action == ACTION_CHOSEN)
{
- if (uiType != POINT_MOTION_TYPE || !instance)
- return;
-
- switch (uiPointId)
- {
- case 1:
- {
- Creature* boss = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_JEDOGA_SHADOWSEEKER));
- if (boss)
- {
- ENSURE_AI(boss_jedoga_shadowseeker::boss_jedoga_shadowseekerAI, boss->AI())->bOpFerok = true;
- ENSURE_AI(boss_jedoga_shadowseeker::boss_jedoga_shadowseekerAI, boss->AI())->bOpFerokFail = false;
- me->KillSelf();
- }
- }
- break;
- }
+ DoCastSelf(SPELL_PILLAR_OF_LIGHTNING);
+ me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL_VOLUNTEER);
+ Talk(SAY_CHOSEN);
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->SetWalk(true);
+ me->GetMotionMaster()->MovePoint(POINT_SACRIFICE, SacrificePosition);
}
+ }
- void UpdateAI(uint32 diff) override
+ void MovementInform(uint32 type, uint32 pointId) override
+ {
+ if (type != POINT_MOTION_TYPE)
+ return;
+
+ switch (pointId)
{
- if (bCheckTimer <= diff)
- {
- if (me->GetGUID() == instance->GetGuidData(DATA_ADD_JEDOGA_OPFER) && !bWalking)
+ case POINT_INITIAL_POSITION:
+ if (Creature* jedoga = _instance->GetCreature(DATA_JEDOGA_SHADOWSEEKER))
+ me->SetFacingToObject(jedoga);
+
+ DoCastSelf(SPELL_SPHERE_VISUAL_VOLUNTEER);
+ me->SetStandState(UNIT_STAND_STATE_KNEEL);
+ break;
+ case POINT_SACRIFICE:
+ if (Creature* jedoga = _instance->GetCreature(DATA_JEDOGA_SHADOWSEEKER))
{
- 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->SetSpeedRate(MOVE_WALK, 0.5f);
- else if (distance < 15.0f)
- me->SetSpeedRate(MOVE_WALK, 0.75f);
- else if (distance < 20.0f)
- me->SetSpeedRate(MOVE_WALK, 1.0f);
-
- me->GetMotionMaster()->Clear(false);
- me->GetMotionMaster()->MovePoint(1, JedogaPosition[1]);
- bWalking = true;
- }
- if (!bWalking)
- {
- if (instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) != 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 (instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) == IN_PROGRESS && !me->HasAura(SPELL_SPHERE_VISUAL))
+ me->SetStandState(UNIT_STAND_STATE_KNEEL);
+ jedoga->AI()->DoAction(ACTION_SACRIFICE);
+ Talk(SAY_SACRIFICED);
+
+ _scheduler.Schedule(Seconds(3), [this](TaskContext /*context*/)
{
- 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);
- }
+ me->SetStandState(UNIT_STAND_STATE_DEAD);
+ me->DespawnOrUnsummon(Seconds(5));
+ });
}
- bCheckTimer = 2*IN_MILLISECONDS;
- } else bCheckTimer -= diff;
-
- //Return since we have no target
- if (!UpdateVictim())
- return;
-
- DoMeleeAttackIfReady();
+ break;
+ default:
+ break;
}
- };
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void UpdateAI(uint32 diff) override
{
- return GetAhnKahetAI<npc_jedoga_initiandAI>(creature);
+ _scheduler.Update(diff);
}
-};
-// ------------------------------------------------------------------------------------------------------------
-// Jedogas Aufseher - Entry: 30181
-// ------------------------------------------------------------------------------------------------------------
-enum AufseherSpell
-{
- SPELL_BEAM_VISUAL_JEDOGAS_AUFSEHER_1 = 60342,
- SPELL_BEAM_VISUAL_JEDOGAS_AUFSEHER_2 = 56312
+private:
+ InstanceScript* _instance;
+ TaskScheduler _scheduler;
};
-class npc_jedogas_aufseher_trigger : public CreatureScript
+// 56328 - Random Lightning Visual Effect
+class spell_random_lightning_visual_effect : public SpellScript
{
-public:
- npc_jedogas_aufseher_trigger() : CreatureScript("npc_jedogas_aufseher_trigger") { }
+ PrepareSpellScript(spell_random_lightning_visual_effect);
- struct npc_jedogas_aufseher_triggerAI : public ScriptedAI
+ void ModDestHeight(SpellDestination& dest)
{
- npc_jedogas_aufseher_triggerAI(Creature* creature) : ScriptedAI(creature)
- {
- instance = creature->GetInstanceScript();
- bRemoved = false;
- bRemoved2 = false;
- bCast = false;
- bCast2 = false;
-
- SetCombatMovement(false);
- }
-
- InstanceScript* instance;
-
- bool bRemoved;
- bool bRemoved2;
- bool bCast;
- bool bCast2;
-
- void Reset() override { }
- void EnterCombat(Unit* /*who*/) override { }
- void AttackStart(Unit* /*victim*/) override { }
- void MoveInLineOfSight(Unit* /*who*/) override { }
-
-
- void UpdateAI(uint32 /*diff*/) override
- {
- if (!bRemoved && me->GetPositionX() > 440.0f)
- {
- if (instance->GetBossState(DATA_PRINCE_TALDARAM) == DONE)
- {
- me->InterruptNonMeleeSpells(true);
- bRemoved = true;
- return;
- }
- if (!bCast)
- {
- DoCast(me, SPELL_BEAM_VISUAL_JEDOGAS_AUFSEHER_1, false);
- bCast = true;
- }
- }
- if (!bRemoved2 && me->GetPositionX() < 440.0f)
- {
- if (!bCast2 && instance->GetData(DATA_JEDOGA_TRIGGER_SWITCH))
- {
- DoCast(me, SPELL_BEAM_VISUAL_JEDOGAS_AUFSEHER_2, false);
- bCast2 = true;
- }
- if (bCast2 && !instance->GetData(DATA_JEDOGA_TRIGGER_SWITCH))
- {
- me->InterruptNonMeleeSpells(true);
- bCast2 = false;
- }
- if (!bRemoved2 && instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) == DONE)
- {
- me->InterruptNonMeleeSpells(true);
- bRemoved2 = true;
- }
- }
- }
- };
+ Position const offset = { 0.0f, 0.0f, -19.0f, 0.0f };
+ dest.RelocateOffset(offset);
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void Register() override
{
- return GetAhnKahetAI<npc_jedogas_aufseher_triggerAI>(creature);
+ OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_random_lightning_visual_effect::ModDestHeight, EFFECT_0, TARGET_DEST_CASTER_RANDOM);
}
+
};
class achievement_volunteer_work : public AchievementCriteriaScript
{
public:
- achievement_volunteer_work() : AchievementCriteriaScript("achievement_volunteer_work")
- {
- }
+ achievement_volunteer_work() : AchievementCriteriaScript("achievement_volunteer_work") { }
bool OnCheck(Player* /*player*/, Unit* target) override
{
if (!target)
return false;
- if (Creature* Jedoga = target->ToCreature())
- if (Jedoga->AI()->GetData(DATA_VOLUNTEER_WORK))
+ if (Creature* jedoga = target->ToCreature())
+ if (jedoga->AI()->GetData(DATA_VOLUNTEER_WORK) == 1)
return true;
return false;
@@ -606,8 +501,8 @@ class achievement_volunteer_work : public AchievementCriteriaScript
void AddSC_boss_jedoga_shadowseeker()
{
- new boss_jedoga_shadowseeker();
- new npc_jedoga_initiand();
- new npc_jedogas_aufseher_trigger();
+ RegisterAhnKahetCreatureAI(boss_jedoga_shadowseeker);
+ RegisterAhnKahetCreatureAI(npc_twilight_volunteer);
+ RegisterSpellScript(spell_random_lightning_visual_effect);
new achievement_volunteer_work();
}
diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp
index fcb37f56a87..8c7f36c3231 100644
--- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp
@@ -53,7 +53,8 @@ enum Spells
enum Misc
{
DATA_EMBRACE_DMG = 20000,
- H_DATA_EMBRACE_DMG = 40000
+ H_DATA_EMBRACE_DMG = 40000,
+ SUMMON_GROUP_CONTROLLERS = 1
};
#define DATA_SPHERE_DISTANCE 25.0f
@@ -104,6 +105,9 @@ class boss_prince_taldaram : public CreatureScript
_flameSphereTargetGUID.Clear();
_embraceTargetGUID.Clear();
_embraceTakenDamage = 0;
+
+ if (!CheckSpheres())
+ me->SummonCreatureGroup(SUMMON_GROUP_CONTROLLERS);
}
void EnterCombat(Unit* /*who*/) override
@@ -125,6 +129,10 @@ class boss_prince_taldaram : public CreatureScript
case NPC_FLAME_SPHERE_2:
case NPC_FLAME_SPHERE_3:
summon->AI()->SetGUID(_flameSphereTargetGUID);
+ break;
+ case NPC_JEDOGA_CONTROLLER:
+ summon->CastSpell(me, SPELL_BEAM_VISUAL);
+ break;
default:
return;
}
@@ -266,13 +274,15 @@ class boss_prince_taldaram : public CreatureScript
void RemovePrison()
{
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ summons.DespawnEntry(NPC_JEDOGA_CONTROLLER);
me->RemoveAurasDueToSpell(SPELL_BEAM_VISUAL);
me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), DATA_GROUND_POSITION_Z, me->GetOrientation());
DoCast(SPELL_HOVER_FALL);
me->SetDisableGravity(false);
me->GetMotionMaster()->MoveLand(0, me->GetHomePosition());
Talk(SAY_WARNING);
- instance->HandleGameObject(instance->GetGuidData(DATA_PRINCE_TALDARAM_PLATFORM), true);
+ if (GameObject* platform = instance->GetGameObject(DATA_PRINCE_TALDARAM_PLATFORM))
+ instance->HandleGameObject(platform->GetGUID(), true);
}
private:
@@ -395,7 +405,7 @@ class go_prince_taldaram_sphere : public GameObjectScript
bool GossipHello(Player* /*player*/) override
{
- Creature* princeTaldaram = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_PRINCE_TALDARAM));
+ Creature* princeTaldaram = instance->GetCreature(DATA_PRINCE_TALDARAM);
if (princeTaldaram && princeTaldaram->IsAlive())
{
me->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp
index c629a5e66e7..9315cf3fddd 100644
--- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp
@@ -16,9 +16,9 @@
*/
#include "ScriptMgr.h"
+#include "AreaBoundary.h"
#include "ahnkahet.h"
#include "Creature.h"
-#include "CreatureAI.h"
#include "GameObject.h"
#include "InstanceScript.h"
#include "Map.h"
@@ -29,6 +29,27 @@ DoorData const doorData[] =
{ 0, 0, DOOR_TYPE_ROOM } // END
};
+ObjectData const creatureData[] =
+{
+ { NPC_ELDER_NADOX, DATA_ELDER_NADOX },
+ { NPC_PRINCE_TALDARAM, DATA_PRINCE_TALDARAM },
+ { NPC_JEDOGA_SHADOWSEEKER, DATA_JEDOGA_SHADOWSEEKER },
+ { NPC_AMANITAR, DATA_AMANITAR },
+ { NPC_HERALD_VOLAZJ, DATA_HERALD_VOLAZJ },
+ { 0, 0 }
+};
+
+ObjectData const gameObjectData[] =
+{
+ { GO_PRINCE_TALDARAM_PLATFORM, DATA_PRINCE_TALDARAM_PLATFORM },
+ { 0, 0 } //END
+};
+
+BossBoundaryData const boundaries =
+{
+ { DATA_JEDOGA_SHADOWSEEKER, new ParallelogramBoundary(Position(460.365f, -661.997f, -20.985f), Position(364.958f,-790.211f, -14.207f), Position(347.436f,-657.978f,14.478f)) }
+};
+
class instance_ahnkahet : public InstanceMapScript
{
public:
@@ -41,46 +62,20 @@ class instance_ahnkahet : public InstanceMapScript
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadDoorData(doorData);
-
- SwitchTrigger = 0;
+ LoadObjectData(creatureData, gameObjectData);
+ LoadBossBoundaries(boundaries);
SpheresState[0] = 0;
SpheresState[1] = 0;
}
- void OnCreatureCreate(Creature* creature) override
- {
- switch (creature->GetEntry())
- {
- case NPC_ELDER_NADOX:
- ElderNadoxGUID = creature->GetGUID();
- break;
- case NPC_PRINCE_TALDARAM:
- PrinceTaldaramGUID = creature->GetGUID();
- break;
- case NPC_JEDOGA_SHADOWSEEKER:
- JedogaShadowseekerGUID = creature->GetGUID();
- break;
- case NPC_AMANITAR:
- AmanitarGUID = creature->GetGUID();
- break;
- case NPC_HERALD_VOLAZJ:
- HeraldVolazjGUID = creature->GetGUID();
- break;
- case NPC_INITIAND:
- InitiandGUIDs.insert(creature->GetGUID());
- break;
- default:
- break;
- }
- }
-
void OnGameObjectCreate(GameObject* go) override
{
+ InstanceScript::OnGameObjectCreate(go);
+
switch (go->GetEntry())
{
case GO_PRINCE_TALDARAM_PLATFORM:
- PrinceTaldaramPlatformGUID = go->GetGUID();
if (GetBossState(DATA_PRINCE_TALDARAM) == DONE)
HandleGameObject(ObjectGuid::Empty, true, go);
break;
@@ -102,21 +97,6 @@ class instance_ahnkahet : public InstanceMapScript
else
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
- case GO_PRINCE_TALDARAM_GATE:
- AddDoor(go, true);
- break;
- default:
- break;
- }
- }
-
- void OnGameObjectRemove(GameObject* go) override
- {
- switch (go->GetEntry())
- {
- case GO_PRINCE_TALDARAM_GATE:
- AddDoor(go, false);
- break;
default:
break;
}
@@ -130,20 +110,6 @@ class instance_ahnkahet : public InstanceMapScript
case DATA_SPHERE_2:
SpheresState[type - DATA_SPHERE_1] = data;
break;
- case DATA_JEDOGA_TRIGGER_SWITCH:
- SwitchTrigger = data;
- break;
- case DATA_JEDOGA_RESET_INITIANDS:
- for (ObjectGuid guid : InitiandGUIDs)
- {
- if (Creature* creature = instance->GetCreature(guid))
- {
- creature->Respawn();
- if (!creature->IsInEvadeMode())
- creature->AI()->EnterEvadeMode();
- }
- }
- break;
default:
break;
}
@@ -156,99 +122,12 @@ class instance_ahnkahet : public InstanceMapScript
case DATA_SPHERE_1:
case DATA_SPHERE_2:
return SpheresState[type - DATA_SPHERE_1];
- case DATA_ALL_INITIAND_DEAD:
- for (ObjectGuid guid : InitiandGUIDs)
- {
- Creature* cr = instance->GetCreature(guid);
- if (!cr || cr->IsAlive())
- return 0;
- }
- return 1;
- case DATA_JEDOGA_TRIGGER_SWITCH:
- return SwitchTrigger;
default:
break;
}
return 0;
}
- void SetGuidData(uint32 type, ObjectGuid data) override
- {
- switch (type)
- {
- case DATA_ADD_JEDOGA_OPFER:
- JedogaSacrifices = data;
- break;
- case DATA_PL_JEDOGA_TARGET:
- JedogaTarget = data;
- break;
- default:
- break;
- }
- }
-
- ObjectGuid GetGuidData(uint32 type) const override
- {
- switch (type)
- {
- case DATA_ELDER_NADOX:
- return ElderNadoxGUID;
- case DATA_PRINCE_TALDARAM:
- return PrinceTaldaramGUID;
- case DATA_JEDOGA_SHADOWSEEKER:
- return JedogaShadowseekerGUID;
- case DATA_AMANITAR:
- return AmanitarGUID;
- case DATA_HERALD_VOLAZJ:
- return HeraldVolazjGUID;
- case DATA_PRINCE_TALDARAM_PLATFORM:
- return PrinceTaldaramPlatformGUID;
- case DATA_ADD_JEDOGA_INITIAND:
- {
- GuidVector vInitiands;
- vInitiands.reserve(InitiandGUIDs.size());
- for (ObjectGuid guid : InitiandGUIDs)
- {
- Creature* cr = instance->GetCreature(guid);
- if (cr && cr->IsAlive())
- vInitiands.push_back(guid);
- }
- if (vInitiands.empty())
- return ObjectGuid::Empty;
-
- return Trinity::Containers::SelectRandomContainerElement(vInitiands);
- }
- case DATA_ADD_JEDOGA_OPFER:
- return JedogaSacrifices;
- case DATA_PL_JEDOGA_TARGET:
- return JedogaTarget;
- default:
- break;
- }
- return ObjectGuid::Empty;
- }
-
- bool SetBossState(uint32 type, EncounterState state) override
- {
- if (!InstanceScript::SetBossState(type, state))
- return false;
-
- switch (type)
- {
- case DATA_JEDOGA_SHADOWSEEKER:
- if (state == DONE)
- {
- for (ObjectGuid guid : InitiandGUIDs)
- if (Creature* cr = instance->GetCreature(guid))
- cr->DespawnOrUnsummon();
- }
- break;
- default:
- break;
- }
- return true;
- }
-
void WriteSaveDataMore(std::ostringstream& data) override
{
data << SpheresState[0] << ' ' << SpheresState[1];
@@ -261,20 +140,7 @@ class instance_ahnkahet : public InstanceMapScript
}
protected:
- ObjectGuid ElderNadoxGUID;
- ObjectGuid PrinceTaldaramGUID;
- ObjectGuid JedogaShadowseekerGUID;
- ObjectGuid AmanitarGUID;
- ObjectGuid HeraldVolazjGUID;
-
- ObjectGuid PrinceTaldaramPlatformGUID;
- ObjectGuid JedogaSacrifices;
- ObjectGuid JedogaTarget;
-
- GuidSet InitiandGUIDs;
-
uint32 SpheresState[2];
- uint8 SwitchTrigger;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/azjol_nerub.h b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/azjol_nerub.h
index 7e42df81f21..f4e8e99b820 100644
--- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/azjol_nerub.h
+++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/azjol_nerub.h
@@ -37,7 +37,8 @@ enum ANDataTypes
DATA_WATCHER_GASHRA,
DATA_WATCHER_SILTHIK,
DATA_ANUBARAK_WALL,
- DATA_ANUBARAK_WALL_2
+ DATA_ANUBARAK_WALL_2,
+ DATA_GATEWATCHER_GREET
};
enum ANCreatureIds
diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp
index 89b5268684d..b10add03865 100644
--- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp
@@ -18,6 +18,7 @@
#include "ScriptMgr.h"
#include "azjol_nerub.h"
#include "InstanceScript.h"
+#include "Map.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "ScriptedCreature.h"
@@ -278,29 +279,22 @@ public:
_anubar.push_back(guid);
}
- void Initialize()
+ void InitializeAI() override
{
+ BossAI::InitializeAI();
me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 9.0f);
me->SetFloatValue(UNIT_FIELD_COMBATREACH, 9.0f);
_enteredCombat = false;
_doorsWebbed = false;
_lastPlayerCombatState = false;
SetStep(0);
- SetCombatMovement(true);
- SummonCrusherPack(SUMMON_GROUP_CRUSHER_1);
- }
-
- void InitializeAI() override
- {
- BossAI::InitializeAI();
- if (me->IsAlive())
- Initialize();
}
- void JustRespawned() override
+ void JustAppeared() override
{
- BossAI::JustRespawned();
- Initialize();
+ BossAI::JustAppeared();
+ SetCombatMovement(true);
+ SummonCrusherPack(SUMMON_GROUP_CRUSHER_1);
}
void UpdateAI(uint32 diff) override
@@ -975,6 +969,8 @@ class spell_hadronox_periodic_summon_template_AuraScript : public AuraScript
InstanceScript* instance = caster->GetInstanceScript();
if (!instance)
return;
+ if (!instance->instance->HavePlayers())
+ return;
if (instance->GetBossState(DATA_HADRONOX) == DONE)
GetAura()->Remove();
else
diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp
index 506ddd8cad2..1df855f2ab0 100644
--- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp
@@ -132,7 +132,7 @@ class boss_krik_thir : public CreatureScript
struct boss_krik_thirAI : public BossAI
{
- boss_krik_thirAI(Creature* creature) : BossAI(creature, DATA_KRIKTHIR), _hadGreet(false), _hadFrenzy(false), _petsInCombat(false), _watchersActive(0) { }
+ boss_krik_thirAI(Creature* creature) : BossAI(creature, DATA_KRIKTHIR), _hadFrenzy(false), _petsInCombat(false), _watchersActive(0) { }
void SummonAdds()
{
@@ -157,15 +157,9 @@ class boss_krik_thir : public CreatureScript
me->SetReactState(REACT_PASSIVE);
}
- void InitializeAI() override
- {
- BossAI::InitializeAI();
- SummonAdds();
- }
-
- void JustRespawned() override
+ void JustAppeared() override
{
- BossAI::JustRespawned();
+ BossAI::JustAppeared();
SummonAdds();
}
@@ -218,9 +212,9 @@ class boss_krik_thir : public CreatureScript
switch (action)
{
case -ACTION_GATEWATCHER_GREET:
- if (!_hadGreet && me->IsAlive() && !me->IsInCombat() && !_petsInCombat)
+ if (!instance->GetData(DATA_GATEWATCHER_GREET) && me->IsAlive() && !me->IsInCombat() && !_petsInCombat)
{
- _hadGreet = true;
+ instance->SetData(DATA_GATEWATCHER_GREET, 1);
Talk(SAY_PREFIGHT);
}
break;
@@ -313,7 +307,6 @@ class boss_krik_thir : public CreatureScript
}
private:
- bool _hadGreet;
bool _hadFrenzy;
bool _petsInCombat;
uint8 _watchersActive;
diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp
index eb6692f0251..49da45c2586 100644
--- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp
@@ -71,14 +71,20 @@ class instance_azjol_nerub : public InstanceMapScript
LoadBossBoundaries(boundaries);
LoadDoorData(doorData);
LoadObjectData(creatureData, gameobjectData);
+ GateWatcherGreet = 0;
}
void OnUnitDeath(Unit* who) override
{
InstanceScript::OnUnitDeath(who);
+
+ if (who->GetTypeId() != TYPEID_UNIT || GetBossState(DATA_KRIKTHIR) == DONE)
+ return;
+
Creature* creature = who->ToCreature();
- if (!creature || creature->IsCritter() || creature->IsControlledByPlayer())
+ if (creature->IsCritter() || creature->IsCharmedOwnedByPlayerOrPlayer())
return;
+
if (Creature* gatewatcher = GetCreature(DATA_KRIKTHIR))
gatewatcher->AI()->DoAction(-ACTION_GATEWATCHER_GREET);
}
@@ -93,6 +99,32 @@ class instance_azjol_nerub : public InstanceMapScript
return true;
}
+
+ uint32 GetData(uint32 type) const override
+ {
+ switch (type)
+ {
+ case DATA_GATEWATCHER_GREET:
+ return GateWatcherGreet;
+ default:
+ return 0;
+ }
+ }
+
+ void SetData(uint32 type, uint32 data) override
+ {
+ switch (type)
+ {
+ case DATA_GATEWATCHER_GREET:
+ GateWatcherGreet = data;
+ break;
+ default:
+ break;
+ }
+ }
+
+ protected:
+ uint8 GateWatcherGreet;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp
index 16955384cb8..24f35115e04 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp
@@ -73,8 +73,7 @@ class boss_baltharus_the_warborn : public CreatureScript
struct boss_baltharus_the_warbornAI : public BossAI
{
- boss_baltharus_the_warbornAI(Creature* creature) : BossAI(creature, DATA_BALTHARUS_THE_WARBORN),
- _cloneCount(0), _introDone(false) { }
+ boss_baltharus_the_warbornAI(Creature* creature) : BossAI(creature, DATA_BALTHARUS_THE_WARBORN), _cloneCount(0) { }
void Reset() override
{
@@ -91,9 +90,6 @@ class boss_baltharus_the_warborn : public CreatureScript
switch (action)
{
case ACTION_INTRO_BALTHARUS:
- if (_introDone)
- return;
- _introDone = true;
me->setActive(true);
events.ScheduleEvent(EVENT_INTRO_TALK, Seconds(7), 0, PHASE_INTRO);
break;
@@ -232,7 +228,6 @@ class boss_baltharus_the_warborn : public CreatureScript
private:
uint8 _cloneCount;
- bool _introDone;
};
CreatureAI* GetAI(Creature* creature) const override
diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
index 472dc16191f..3957ad4793c 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
@@ -566,7 +566,7 @@ class npc_halion_controller : public CreatureScript
_twilightDamageTaken = 0;
}
- void JustRespawned() override
+ void JustAppeared() override
{
if (_instance->GetGuidData(DATA_HALION) || _instance->GetBossState(DATA_GENERAL_ZARITHRIAN) != DONE)
return;
@@ -733,7 +733,7 @@ class npc_halion_controller : public CreatureScript
case EVENT_TWILIGHT_MENDING:
if (_instance->GetCreature(DATA_HALION)) // Just check if physical Halion is spawned
if (Creature* twilightHalion = _instance->GetCreature(DATA_TWILIGHT_HALION))
- twilightHalion->CastSpell((Unit*)nullptr, SPELL_TWILIGHT_MENDING, true);
+ twilightHalion->CastSpell(nullptr, SPELL_TWILIGHT_MENDING, true);
break;
case EVENT_TRIGGER_BERSERK:
for (uint8 i = DATA_HALION; i <= DATA_TWILIGHT_HALION; i++)
@@ -921,7 +921,7 @@ class npc_orb_carrier : public CreatureScript
/// However, refreshing it looks bad, so just cast the spell if
/// we are not channeling it.
if (!me->HasUnitState(UNIT_STATE_CASTING))
- me->CastSpell((Unit*)nullptr, SPELL_TRACK_ROTATION, false);
+ me->CastSpell(nullptr, SPELL_TRACK_ROTATION, false);
scheduler.Update(diff);
diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.cpp
index e43b93e484d..20d8333bbab 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.cpp
@@ -152,12 +152,12 @@ class npc_xerestrasza : public CreatureScript
}
};
-class at_baltharus_plateau : public AreaTriggerScript
+class at_baltharus_plateau : public OnlyOnceAreaTriggerScript
{
public:
- at_baltharus_plateau() : AreaTriggerScript("at_baltharus_plateau") { }
+ at_baltharus_plateau() : OnlyOnceAreaTriggerScript("at_baltharus_plateau") { }
- bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
+ bool _OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
{
// Only trigger once
if (InstanceScript* instance = player->GetInstanceScript())
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp
index 1061dc37aff..3b997fe9516 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp
@@ -505,9 +505,9 @@ public:
npc_argent_soldier() : CreatureScript("npc_argent_soldier") { }
// THIS AI NEEDS MORE IMPROVEMENTS
- struct npc_argent_soldierAI : public npc_escortAI
+ struct npc_argent_soldierAI : public EscortAI
{
- npc_argent_soldierAI(Creature* creature) : npc_escortAI(creature)
+ npc_argent_soldierAI(Creature* creature) : EscortAI(creature)
{
instance = creature->GetInstanceScript();
me->SetReactState(REACT_DEFENSIVE);
@@ -519,7 +519,7 @@ public:
uint8 uiWaypoint;
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (waypointId == 0)
{
@@ -592,7 +592,7 @@ public:
void UpdateAI(uint32 uiDiff) override
{
- npc_escortAI::UpdateAI(uiDiff);
+ EscortAI::UpdateAI(uiDiff);
if (!UpdateVictim())
return;
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp
index be1c5b69bd8..c64222cc61c 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp
@@ -354,18 +354,16 @@ class npc_black_knight_skeletal_gryphon : public CreatureScript
public:
npc_black_knight_skeletal_gryphon() : CreatureScript("npc_black_knight_skeletal_gryphon") { }
- struct npc_black_knight_skeletal_gryphonAI : public npc_escortAI
+ struct npc_black_knight_skeletal_gryphonAI : public EscortAI
{
- npc_black_knight_skeletal_gryphonAI(Creature* creature) : npc_escortAI(creature)
+ npc_black_knight_skeletal_gryphonAI(Creature* creature) : EscortAI(creature)
{
Start(false, true);
}
- void WaypointReached(uint32 /*waypointId*/) override { }
-
void UpdateAI(uint32 uiDiff) override
{
- npc_escortAI::UpdateAI(uiDiff);
+ EscortAI::UpdateAI(uiDiff);
UpdateVictim();
}
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp
index e0d59e6b4d5..fb2e461da0e 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp
@@ -114,7 +114,7 @@ void AggroAllPlayers(Creature* temp)
temp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
temp->SetImmuneToPC(true);
temp->SetReactState(REACT_AGGRESSIVE);
- temp->EngageWithTarget(player);
+ temp->EngageWithTarget(player);
}
}
}
@@ -152,9 +152,9 @@ class generic_vehicleAI_toc5 : public CreatureScript
public:
generic_vehicleAI_toc5() : CreatureScript("generic_vehicleAI_toc5") { }
- struct generic_vehicleAI_toc5AI : public npc_escortAI
+ struct generic_vehicleAI_toc5AI : public EscortAI
{
- generic_vehicleAI_toc5AI(Creature* creature) : npc_escortAI(creature)
+ generic_vehicleAI_toc5AI(Creature* creature) : EscortAI(creature)
{
Initialize();
SetDespawnAtEnd(false);
@@ -212,7 +212,7 @@ public:
Start(false, true);
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -239,7 +239,7 @@ public:
void UpdateAI(uint32 uiDiff) override
{
- npc_escortAI::UpdateAI(uiDiff);
+ EscortAI::UpdateAI(uiDiff);
if (!UpdateVictim())
return;
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp
index efedf67069f..955e7ff313c 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp
@@ -463,7 +463,7 @@ public:
instance->GetData(BOSS_ARGENT_CHALLENGE_P) == NOT_STARTED &&
instance->GetData(BOSS_BLACK_KNIGHT) == NOT_STARTED)
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_START_EVENT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- else if (instance)
+ else
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_START_EVENT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp
index 72ac4f0e499..4d3f243a4a7 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp
@@ -168,7 +168,7 @@ class boss_anubarak_trial : public CreatureScript
struct boss_anubarak_trialAI : public BossAI
{
- boss_anubarak_trialAI(Creature* creature) : BossAI(creature, BOSS_ANUBARAK)
+ boss_anubarak_trialAI(Creature* creature) : BossAI(creature, DATA_ANUBARAK)
{
Initialize();
}
@@ -223,7 +223,7 @@ class boss_anubarak_trial : public CreatureScript
void JustReachedHome() override
{
- instance->SetBossState(BOSS_ANUBARAK, FAIL);
+ instance->SetBossState(DATA_ANUBARAK, FAIL);
//Summon Scarab Swarms neutral at random places
for (int i = 0; i < 10; i++)
if (Creature* scarab = me->SummonCreature(NPC_SCARAB, AnubarakLoc[1].GetPositionX()+urand(0, 50)-25, AnubarakLoc[1].GetPositionY()+urand(0, 50)-25, AnubarakLoc[1].GetPositionZ()))
@@ -461,8 +461,8 @@ class npc_swarm_scarab : public CreatureScript
DoCast(me, SPELL_ACID_MANDIBLE);
me->SetInCombatWithZone();
if (me->IsInCombat())
- if (Creature* Anubarak = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_ANUBARAK)))
- Anubarak->AI()->JustSummoned(me);
+ if (Creature* anubarak = _instance->GetCreature(DATA_ANUBARAK))
+ anubarak->AI()->JustSummoned(me);
}
void DoAction(int32 actionId) override
@@ -485,7 +485,7 @@ class npc_swarm_scarab : public CreatureScript
void UpdateAI(uint32 diff) override
{
- if (_instance->GetBossState(BOSS_ANUBARAK) != IN_PROGRESS)
+ if (_instance->GetBossState(DATA_ANUBARAK) != IN_PROGRESS)
me->DisappearAndDie();
if (!UpdateVictim())
@@ -541,8 +541,8 @@ class npc_nerubian_burrower : public CreatureScript
DoCast(me, SPELL_AWAKENED);
me->SetInCombatWithZone();
if (me->IsInCombat())
- if (Creature* Anubarak = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_ANUBARAK)))
- Anubarak->AI()->JustSummoned(me);
+ if (Creature* anubarak = _instance->GetCreature(DATA_ANUBARAK))
+ anubarak->AI()->JustSummoned(me);
}
void DoAction(int32 actionId) override
@@ -561,7 +561,7 @@ class npc_nerubian_burrower : public CreatureScript
void UpdateAI(uint32 diff) override
{
- if (_instance->GetBossState(BOSS_ANUBARAK) != IN_PROGRESS)
+ if (_instance->GetBossState(DATA_ANUBARAK) != IN_PROGRESS)
me->DisappearAndDie();
if (!UpdateVictim() && !me->HasAura(SPELL_SUBMERGE_EFFECT))
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp
index fc2d5c466cc..be5772f191f 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp
@@ -375,12 +375,11 @@ class boss_toc_champion_controller : public CreatureScript
public:
boss_toc_champion_controller() : CreatureScript("boss_toc_champion_controller") { }
- struct boss_toc_champion_controllerAI : public ScriptedAI
+ struct boss_toc_champion_controllerAI : public BossAI
{
- boss_toc_champion_controllerAI(Creature* creature) : ScriptedAI(creature), _summons(me)
+ boss_toc_champion_controllerAI(Creature* creature) : BossAI(creature, DATA_FACTION_CRUSADERS)
{
Initialize();
- _instance = creature->GetInstanceScript();
}
void Initialize()
@@ -396,6 +395,8 @@ class boss_toc_champion_controller : public CreatureScript
Initialize();
}
+ void JustSummoned(Creature* /*summon*/) override { }
+
std::vector<uint32> SelectChampions(Team playerTeam)
{
std::vector<uint32> vHealersEntries;
@@ -415,7 +416,7 @@ class boss_toc_champion_controller : public CreatureScript
vOtherEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_WARRIOR : NPC_ALLIANCE_WARRIOR);
uint8 healersSubtracted = 2;
- if (_instance->instance->GetSpawnMode() == RAID_DIFFICULTY_25MAN_NORMAL || _instance->instance->GetSpawnMode() == RAID_DIFFICULTY_25MAN_HEROIC)
+ if (instance->instance->GetSpawnMode() == RAID_DIFFICULTY_25MAN_NORMAL || instance->instance->GetSpawnMode() == RAID_DIFFICULTY_25MAN_HEROIC)
healersSubtracted = 1;
for (uint8 i = 0; i < healersSubtracted; ++i)
{
@@ -452,7 +453,7 @@ class boss_toc_champion_controller : public CreatureScript
vHealersEntries.erase(vHealersEntries.begin() + pos);
}
- if (_instance->instance->GetSpawnMode() == RAID_DIFFICULTY_10MAN_NORMAL || _instance->instance->GetSpawnMode() == RAID_DIFFICULTY_10MAN_HEROIC)
+ if (instance->instance->GetSpawnMode() == RAID_DIFFICULTY_10MAN_NORMAL || instance->instance->GetSpawnMode() == RAID_DIFFICULTY_10MAN_HEROIC)
for (uint8 i = 0; i < 4; ++i)
vOtherEntries.erase(vOtherEntries.begin() + urand(0, vOtherEntries.size() - 1));
@@ -486,7 +487,7 @@ class boss_toc_champion_controller : public CreatureScript
uint8 pos = urand(0, vChampionJumpTarget.size()-1);
if (Creature* champion = me->SummonCreature(vChampionEntries[i], vChampionJumpOrigin[urand(0, vChampionJumpOrigin.size()-1)], TEMPSUMMON_MANUAL_DESPAWN))
{
- _summons.Summon(champion);
+ summons.Summon(champion);
champion->SetReactState(REACT_PASSIVE);
champion->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
champion->SetImmuneToPC(false);
@@ -515,7 +516,7 @@ class boss_toc_champion_controller : public CreatureScript
SummonChampions((Team)uiData);
break;
case 1:
- for (SummonList::iterator i = _summons.begin(); i != _summons.end(); ++i)
+ for (SummonList::iterator i = summons.begin(); i != summons.end(); ++i)
{
if (Creature* summon = ObjectAccessor::GetCreature(*me, *i))
{
@@ -530,10 +531,10 @@ class boss_toc_champion_controller : public CreatureScript
{
case FAIL:
_championsFailed++;
- if (_championsFailed + _championsKilled >= _summons.size())
+ if (_championsFailed + _championsKilled >= summons.size())
{
- _instance->SetBossState(BOSS_CRUSADERS, FAIL);
- _summons.DespawnAll();
+ instance->SetBossState(DATA_FACTION_CRUSADERS, FAIL);
+ summons.DespawnAll();
me->DespawnOrUnsummon();
}
break;
@@ -544,21 +545,23 @@ class boss_toc_champion_controller : public CreatureScript
_championsFailed = 0;
_championsKilled = 0;
_inProgress = true;
- _summons.DoZoneInCombat();
- _instance->SetBossState(BOSS_CRUSADERS, IN_PROGRESS);
+ summons.DoZoneInCombat();
+ instance->SetBossState(DATA_FACTION_CRUSADERS, IN_PROGRESS);
}
break;
case DONE:
+ {
_championsKilled++;
if (_championsKilled == 1)
- _instance->SetBossState(BOSS_CRUSADERS, SPECIAL);
- else if (_championsKilled >= _summons.size())
+ instance->SetBossState(DATA_FACTION_CRUSADERS, SPECIAL);
+ else if (_championsKilled >= summons.size())
{
- _instance->SetBossState(BOSS_CRUSADERS, DONE);
- _summons.DespawnAll();
+ instance->SetBossState(DATA_FACTION_CRUSADERS, DONE);
+ summons.DespawnAll();
me->DespawnOrUnsummon();
}
break;
+ }
default:
break;
}
@@ -568,8 +571,6 @@ class boss_toc_champion_controller : public CreatureScript
}
}
private:
- InstanceScript* _instance;
- SummonList _summons;
uint32 _championsNotStarted;
uint32 _championsFailed;
uint32 _championsKilled;
@@ -584,9 +585,10 @@ class boss_toc_champion_controller : public CreatureScript
struct boss_faction_championsAI : public BossAI
{
- boss_faction_championsAI(Creature* creature, uint32 aitype) : BossAI(creature, BOSS_CRUSADERS)
+ boss_faction_championsAI(Creature* creature, uint32 aitype) : BossAI(creature, DATA_FACTION_CHAMPIONS)
{
_aiType = aitype;
+ SetBoundary(instance->GetBossBoundary(DATA_FACTION_CRUSADERS));
}
void Reset() override
@@ -598,7 +600,7 @@ struct boss_faction_championsAI : public BossAI
void JustReachedHome() override
{
- if (Creature* pChampionController = ObjectAccessor::GetCreature((*me), instance->GetGuidData(NPC_CHAMPIONS_CONTROLLER)))
+ if (Creature* pChampionController = instance->GetCreature(DATA_FACTION_CRUSADERS))
pChampionController->AI()->SetData(2, FAIL);
me->DespawnOrUnsummon();
}
@@ -637,15 +639,17 @@ struct boss_faction_championsAI : public BossAI
void JustDied(Unit* /*killer*/) override
{
if (_aiType != AI_PET)
- if (Creature* pChampionController = ObjectAccessor::GetCreature((*me), instance->GetGuidData(NPC_CHAMPIONS_CONTROLLER)))
+ if (Creature* pChampionController = instance->GetCreature(DATA_FACTION_CRUSADERS))
pChampionController->AI()->SetData(2, DONE);
}
void EnterCombat(Unit* /*who*/) override
{
DoCast(me, SPELL_ANTI_AOE, true);
- _EnterCombat();
- if (Creature* pChampionController = ObjectAccessor::GetCreature((*me), instance->GetGuidData(NPC_CHAMPIONS_CONTROLLER)))
+ me->SetCombatPulseDelay(5);
+ me->setActive(true);
+ DoZoneInCombat();
+ if (Creature* pChampionController = instance->GetCreature(DATA_FACTION_CRUSADERS))
pChampionController->AI()->SetData(2, IN_PROGRESS);
}
@@ -662,11 +666,11 @@ struct boss_faction_championsAI : public BossAI
if (TeamInInstance == ALLIANCE)
{
- if (Creature* varian = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_VARIAN)))
+ if (Creature* varian = instance->GetCreature(DATA_VARIAN))
varian->AI()->Talk(SAY_KILL_PLAYER);
}
else
- if (Creature* garrosh = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_GARROSH)))
+ if (Creature* garrosh = instance->GetCreature(DATA_GARROSH))
garrosh->AI()->Talk(SAY_KILL_PLAYER);
}
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp
index 8f50ed0e365..8b32acdadb5 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp
@@ -102,7 +102,7 @@ class boss_jaraxxus : public CreatureScript
struct boss_jaraxxusAI : public BossAI
{
- boss_jaraxxusAI(Creature* creature) : BossAI(creature, BOSS_JARAXXUS) { }
+ boss_jaraxxusAI(Creature* creature) : BossAI(creature, DATA_JARAXXUS) { }
void Reset() override
{
@@ -119,7 +119,7 @@ class boss_jaraxxus : public CreatureScript
void JustReachedHome() override
{
_JustReachedHome();
- instance->SetBossState(BOSS_JARAXXUS, FAIL);
+ instance->SetBossState(DATA_JARAXXUS, FAIL);
DoCast(me, SPELL_JARAXXUS_CHAINS);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->SetImmuneToPC(true);
@@ -238,7 +238,7 @@ class npc_legion_flame : public CreatureScript
void UpdateAI(uint32 /*diff*/) override
{
UpdateVictim();
- if (_instance->GetBossState(BOSS_JARAXXUS) != IN_PROGRESS)
+ if (_instance->GetBossState(DATA_JARAXXUS) != IN_PROGRESS)
me->DespawnOrUnsummon();
}
private:
@@ -330,7 +330,7 @@ class npc_fel_infernal : public CreatureScript
void UpdateAI(uint32 diff) override
{
- if (_instance->GetBossState(BOSS_JARAXXUS) != IN_PROGRESS)
+ if (_instance->GetBossState(DATA_JARAXXUS) != IN_PROGRESS)
{
me->DespawnOrUnsummon();
return;
@@ -438,7 +438,7 @@ class npc_mistress_of_pain : public CreatureScript
void UpdateAI(uint32 diff) override
{
- if (_instance->GetBossState(BOSS_JARAXXUS) != IN_PROGRESS)
+ if (_instance->GetBossState(DATA_JARAXXUS) != IN_PROGRESS)
{
me->DespawnOrUnsummon();
return;
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
index 17ce9458905..772edda63c6 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
@@ -179,7 +179,10 @@ class boss_gormok : public CreatureScript
struct boss_gormokAI : public BossAI
{
- boss_gormokAI(Creature* creature) : BossAI(creature, BOSS_BEASTS) { }
+ boss_gormokAI(Creature* creature) : BossAI(creature, DATA_GORMOK_THE_IMPALER)
+ {
+ SetBoundary(instance->GetBossBoundary(DATA_NORTHREND_BEASTS));
+ }
void Reset() override
{
@@ -192,7 +195,7 @@ class boss_gormok : public CreatureScript
void EnterEvadeMode(EvadeReason why) override
{
- instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR));
+ instance->DoUseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
ScriptedAI::EnterEvadeMode(why);
}
@@ -204,7 +207,7 @@ class boss_gormok : public CreatureScript
switch (pointId)
{
case 0:
- instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR));
+ instance->DoUseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
me->SetImmuneToPC(false);
me->SetReactState(REACT_AGGRESSIVE);
@@ -222,7 +225,7 @@ class boss_gormok : public CreatureScript
void JustReachedHome() override
{
- instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR));
+ instance->DoUseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
instance->SetData(TYPE_NORTHREND_BEASTS, FAIL);
me->DespawnOrUnsummon();
@@ -230,8 +233,11 @@ class boss_gormok : public CreatureScript
void EnterCombat(Unit* /*who*/) override
{
- _EnterCombat();
+ me->SetCombatPulseDelay(5);
+ me->setActive(true);
+ //DoZoneInCombat();
instance->SetData(TYPE_NORTHREND_BEASTS, GORMOK_IN_PROGRESS);
+ instance->SetBossState(DATA_NORTHREND_BEASTS, IN_PROGRESS);
}
void DamageTaken(Unit* /*who*/, uint32& damage) override
@@ -387,7 +393,7 @@ class npc_snobold_vassal : public CreatureScript
void MountOnBoss()
{
- Unit* gormok = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_GORMOK));
+ Unit* gormok = _instance->GetCreature(DATA_GORMOK_THE_IMPALER);
if (gormok && gormok->IsAlive())
{
me->AttackStop();
@@ -511,7 +517,7 @@ class npc_firebomb : public CreatureScript
struct boss_jormungarAI : public BossAI
{
- boss_jormungarAI(Creature* creature) : BossAI(creature, BOSS_BEASTS)
+ boss_jormungarAI(Creature* creature, uint32 bossId) : BossAI(creature, bossId)
{
OtherWormEntry = 0;
ModelStationary = 0;
@@ -525,6 +531,7 @@ struct boss_jormungarAI : public BossAI
Phase = PHASE_MOBILE;
Enraged = false;
WasMobile = false;
+ SetBoundary(instance->GetBossBoundary(DATA_NORTHREND_BEASTS));
}
void Reset() override
@@ -539,9 +546,14 @@ struct boss_jormungarAI : public BossAI
events.ScheduleEvent(EVENT_SLIME_POOL, 15*IN_MILLISECONDS, 0, PHASE_MOBILE);
}
+ uint32 GetOtherWormData(uint32 wormEntry)
+ {
+ return wormEntry == NPC_ACIDMAW ? DATA_ACIDMAW : DATA_DREADSCALE;
+ }
+
void JustDied(Unit* /*killer*/) override
{
- if (Creature* otherWorm = ObjectAccessor::GetCreature(*me, instance->GetGuidData(OtherWormEntry)))
+ if (Creature* otherWorm = instance->GetCreature(GetOtherWormData(OtherWormEntry)))
{
if (!otherWorm->IsAlive())
{
@@ -714,7 +726,7 @@ class boss_acidmaw : public CreatureScript
struct boss_acidmawAI : public boss_jormungarAI
{
- boss_acidmawAI(Creature* creature) : boss_jormungarAI(creature) { }
+ boss_acidmawAI(Creature* creature) : boss_jormungarAI(creature, DATA_ACIDMAW) { }
void Reset() override
{
@@ -745,7 +757,7 @@ class boss_dreadscale : public CreatureScript
struct boss_dreadscaleAI : public boss_jormungarAI
{
- boss_dreadscaleAI(Creature* creature) : boss_jormungarAI(creature) { }
+ boss_dreadscaleAI(Creature* creature) : boss_jormungarAI(creature, DATA_DREADSCALE) { }
void Reset() override
{
@@ -772,7 +784,7 @@ class boss_dreadscale : public CreatureScript
switch (pointId)
{
case 0:
- instance->DoCloseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR));
+ instance->DoCloseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
me->SetImmuneToPC(false);
me->SetReactState(REACT_AGGRESSIVE);
@@ -785,13 +797,13 @@ class boss_dreadscale : public CreatureScript
void EnterEvadeMode(EvadeReason why) override
{
- instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR));
+ instance->DoUseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
boss_jormungarAI::EnterEvadeMode(why);
}
void JustReachedHome() override
{
- instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR));
+ instance->DoUseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
boss_jormungarAI::JustReachedHome();
}
@@ -887,9 +899,10 @@ class boss_icehowl : public CreatureScript
struct boss_icehowlAI : public BossAI
{
- boss_icehowlAI(Creature* creature) : BossAI(creature, BOSS_BEASTS)
+ boss_icehowlAI(Creature* creature) : BossAI(creature, DATA_ICEHOWL)
{
Initialize();
+ SetBoundary(instance->GetBossBoundary(DATA_NORTHREND_BEASTS));
}
void Initialize()
@@ -946,7 +959,7 @@ class boss_icehowl : public CreatureScript
_movementFinish = true;
break;
case 2:
- instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR));
+ instance->DoUseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
me->SetImmuneToPC(false);
me->SetReactState(REACT_AGGRESSIVE);
@@ -959,13 +972,13 @@ class boss_icehowl : public CreatureScript
void EnterEvadeMode(EvadeReason why) override
{
- instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR));
+ instance->DoUseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
ScriptedAI::EnterEvadeMode(why);
}
void JustReachedHome() override
{
- instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR));
+ instance->DoUseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
instance->SetData(TYPE_NORTHREND_BEASTS, FAIL);
me->DespawnOrUnsummon();
}
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp
index 49bd28f7e56..7050f20c1c9 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp
@@ -158,9 +158,14 @@ class OrbsDespawner : public BasicEvent
Creature* _creature;
};
+static uint32 GetSisterData(uint32 sisterEntry)
+{
+ return sisterEntry == NPC_FJOLA_LIGHTBANE ? DATA_FJOLA_LIGHTBANE : DATA_EYDIS_DARKBANE;
+}
+
struct boss_twin_baseAI : public BossAI
{
- boss_twin_baseAI(Creature* creature) : BossAI(creature, BOSS_VALKIRIES)
+ boss_twin_baseAI(Creature* creature, uint32 bossId) : BossAI(creature, bossId)
{
AuraState = AURA_STATE_NONE;
Weapon = 0;
@@ -173,6 +178,7 @@ struct boss_twin_baseAI : public BossAI
TwinPactSpellId = 0;
SpikeSpellId = 0;
TouchSpellId = 0;
+ SetBoundary(instance->GetBossBoundary(DATA_TWIN_VALKIRIES));
}
void Reset() override
@@ -189,7 +195,7 @@ struct boss_twin_baseAI : public BossAI
void JustReachedHome() override
{
- instance->SetBossState(BOSS_VALKIRIES, FAIL);
+ instance->SetBossState(DATA_TWIN_VALKIRIES, FAIL);
summons.DespawnAll();
me->DespawnOrUnsummon();
@@ -248,12 +254,14 @@ struct boss_twin_baseAI : public BossAI
{
me->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
pSister->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
- _JustDied();
+ events.Reset();
+ summons.DespawnAll();
+ instance->SetBossState(DATA_TWIN_VALKIRIES, DONE);
}
else
{
me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
- instance->SetBossState(BOSS_VALKIRIES, SPECIAL);
+ instance->SetBossState(DATA_TWIN_VALKIRIES, SPECIAL);
}
}
summons.DespawnAll();
@@ -262,7 +270,7 @@ struct boss_twin_baseAI : public BossAI
// Called when sister pointer needed
Creature* GetSister()
{
- return ObjectAccessor::GetCreature((*me), instance->GetGuidData(SisterNpcId));
+ return instance->GetCreature(GetSisterData(SisterNpcId));
}
void EnterCombat(Unit* /*who*/) override
@@ -273,10 +281,12 @@ struct boss_twin_baseAI : public BossAI
me->AddAura(MyEmphatySpellId, pSister);
pSister->SetInCombatWithZone();
}
- instance->SetBossState(BOSS_VALKIRIES, IN_PROGRESS);
+ instance->SetBossState(DATA_TWIN_VALKIRIES, IN_PROGRESS);
Talk(SAY_AGGRO);
DoCast(me, SurgeSpellId);
+ me->SetCombatPulseDelay(5);
+ me->setActive(true);
events.ScheduleEvent(EVENT_TWIN_SPIKE, 20 * IN_MILLISECONDS);
events.ScheduleEvent(EVENT_BERSERK, IsHeroic() ? 6 * MINUTE*IN_MILLISECONDS : 10 * MINUTE*IN_MILLISECONDS);
@@ -354,7 +364,7 @@ class boss_fjola : public CreatureScript
struct boss_fjolaAI : public boss_twin_baseAI
{
- boss_fjolaAI(Creature* creature) : boss_twin_baseAI(creature)
+ boss_fjolaAI(Creature* creature) : boss_twin_baseAI(creature, DATA_FJOLA_LIGHTBANE)
{
GenerateStageSequence();
}
@@ -364,7 +374,7 @@ class boss_fjola : public CreatureScript
SetEquipmentSlots(false, EQUIP_MAIN_1, EQUIP_UNEQUIP, EQUIP_NO_CHANGE);
Weapon = EQUIP_MAIN_1;
AuraState = AURA_STATE_UNKNOWN22;
- SisterNpcId = NPC_DARKBANE;
+ SisterNpcId = NPC_EYDIS_DARKBANE;
MyEmphatySpellId = SPELL_TWIN_EMPATHY_DARK;
OtherEssenceSpellId = SPELL_DARK_ESSENCE_HELPER;
SurgeSpellId = SPELL_LIGHT_SURGE;
@@ -421,13 +431,13 @@ class boss_fjola : public CreatureScript
void EnterEvadeMode(EvadeReason why) override
{
- instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR));
+ instance->DoUseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
boss_twin_baseAI::EnterEvadeMode(why);
}
void JustReachedHome() override
{
- instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR));
+ instance->DoUseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
boss_twin_baseAI::JustReachedHome();
}
@@ -465,14 +475,14 @@ class boss_eydis : public CreatureScript
struct boss_eydisAI : public boss_twin_baseAI
{
- boss_eydisAI(Creature* creature) : boss_twin_baseAI(creature) { }
+ boss_eydisAI(Creature* creature) : boss_twin_baseAI(creature, DATA_EYDIS_DARKBANE) { }
void Reset() override
{
SetEquipmentSlots(false, EQUIP_MAIN_2, EQUIP_UNEQUIP, EQUIP_NO_CHANGE);
Weapon = EQUIP_MAIN_2;
AuraState = AURA_STATE_UNKNOWN19;
- SisterNpcId = NPC_LIGHTBANE;
+ SisterNpcId = NPC_FJOLA_LIGHTBANE;
MyEmphatySpellId = SPELL_TWIN_EMPATHY_LIGHT;
OtherEssenceSpellId = SPELL_LIGHT_ESSENCE_HELPER;
SurgeSpellId = SPELL_DARK_SURGE;
@@ -860,8 +870,8 @@ class spell_power_of_the_twins : public SpellScriptLoader
{
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
{
- if (Creature* Valk = ObjectAccessor::GetCreature(*GetCaster(), instance->GetGuidData(GetCaster()->GetEntry())))
- ENSURE_AI(boss_twin_baseAI, Valk->AI())->EnableDualWield(true);
+ if (Creature* valk = instance->GetCreature(GetSisterData(GetCaster()->GetEntry())))
+ ENSURE_AI(boss_twin_baseAI, valk->AI())->EnableDualWield(true);
}
}
@@ -869,8 +879,8 @@ class spell_power_of_the_twins : public SpellScriptLoader
{
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
{
- if (Creature* Valk = ObjectAccessor::GetCreature(*GetCaster(), instance->GetGuidData(GetCaster()->GetEntry())))
- ENSURE_AI(boss_twin_baseAI, Valk->AI())->EnableDualWield(false);
+ if (Creature* valk = instance->GetCreature(GetSisterData(GetCaster()->GetEntry())))
+ ENSURE_AI(boss_twin_baseAI, valk->AI())->EnableDualWield(false);
}
}
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp
index 506f076be33..28891678aef 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp
@@ -29,11 +29,53 @@
BossBoundaryData const boundaries =
{
- { BOSS_BEASTS, new CircleBoundary(Position(563.26f, 139.6f), 75.0) },
- { BOSS_JARAXXUS, new CircleBoundary(Position(563.26f, 139.6f), 75.0) },
- { BOSS_CRUSADERS, new CircleBoundary(Position(563.26f, 139.6f), 75.0) },
- { BOSS_VALKIRIES, new CircleBoundary(Position(563.26f, 139.6f), 75.0) },
- { BOSS_ANUBARAK, new EllipseBoundary(Position(746.0f, 135.0f), 100.0, 75.0) }
+ { DATA_NORTHREND_BEASTS, new CircleBoundary(Position(563.26f, 139.6f), 75.0) },
+ { DATA_JARAXXUS, new CircleBoundary(Position(563.26f, 139.6f), 75.0) },
+ { DATA_FACTION_CRUSADERS, new CircleBoundary(Position(563.26f, 139.6f), 75.0) },
+ { DATA_TWIN_VALKIRIES, new CircleBoundary(Position(563.26f, 139.6f), 75.0) },
+ { DATA_ANUBARAK, new EllipseBoundary(Position(746.0f, 135.0f), 100.0, 75.0) }
+};
+
+ObjectData const creatureData[] =
+{
+ { NPC_GORMOK, DATA_GORMOK_THE_IMPALER },
+ { NPC_ACIDMAW, DATA_ACIDMAW },
+ { NPC_DREADSCALE, DATA_DREADSCALE },
+ { NPC_ICEHOWL, DATA_ICEHOWL },
+ { NPC_JARAXXUS, DATA_JARAXXUS },
+ { NPC_CHAMPIONS_CONTROLLER, DATA_FACTION_CRUSADERS },
+ { NPC_FJOLA_LIGHTBANE, DATA_FJOLA_LIGHTBANE },
+ { NPC_EYDIS_DARKBANE, DATA_EYDIS_DARKBANE },
+ { NPC_LICH_KING, DATA_LICH_KING },
+ { NPC_ANUBARAK, DATA_ANUBARAK },
+ { NPC_BARRET_RAMSEY, DATA_BARRET_RAMSEY },
+ { NPC_TIRION_FORDRING, DATA_FORDRING },
+ { NPC_TIRION_FORDRING_ANUBARAK, DATA_FORDRING_ANUBARAK },
+ { NPC_VARIAN, DATA_VARIAN },
+ { NPC_GARROSH, DATA_GARROSH },
+ { NPC_FIZZLEBANG, DATA_FIZZLEBANG },
+ { 0, 0 } // END
+};
+
+ObjectData const gameObjectData[] =
+{
+ { GO_CRUSADERS_CACHE_10, DATA_CRUSADERS_CHEST },
+ { GO_CRUSADERS_CACHE_25, DATA_CRUSADERS_CHEST },
+ { GO_CRUSADERS_CACHE_10_H, DATA_CRUSADERS_CHEST },
+ { GO_CRUSADERS_CACHE_25_H, DATA_CRUSADERS_CHEST },
+ { GO_ARGENT_COLISEUM_FLOOR, DATA_COLISEUM_FLOOR },
+ { GO_MAIN_GATE_DOOR, DATA_MAIN_GATE },
+ { GO_EAST_PORTCULLIS, DATA_EAST_PORTCULLIS },
+ { GO_WEB_DOOR, DATA_WEB_DOOR },
+ { GO_TRIBUTE_CHEST_10H_25, DATA_TRIBUTE_CHEST },
+ { GO_TRIBUTE_CHEST_10H_45, DATA_TRIBUTE_CHEST },
+ { GO_TRIBUTE_CHEST_10H_50, DATA_TRIBUTE_CHEST },
+ { GO_TRIBUTE_CHEST_10H_99, DATA_TRIBUTE_CHEST },
+ { GO_TRIBUTE_CHEST_25H_25, DATA_TRIBUTE_CHEST },
+ { GO_TRIBUTE_CHEST_25H_45, DATA_TRIBUTE_CHEST },
+ { GO_TRIBUTE_CHEST_25H_50, DATA_TRIBUTE_CHEST },
+ { GO_TRIBUTE_CHEST_25H_99, DATA_TRIBUTE_CHEST },
+ { 0, 0 } // END
};
class instance_trial_of_the_crusader : public InstanceMapScript
@@ -46,8 +88,9 @@ class instance_trial_of_the_crusader : public InstanceMapScript
instance_trial_of_the_crusader_InstanceMapScript(Map* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
- SetBossNumber(MAX_ENCOUNTERS);
+ SetBossNumber(EncounterCount);
LoadBossBoundaries(boundaries);
+ LoadObjectData(creatureData, gameObjectData);
TrialCounter = 50;
EventStage = 0;
NorthrendBeasts = NOT_STARTED;
@@ -62,12 +105,12 @@ class instance_trial_of_the_crusader : public InstanceMapScript
bool IsEncounterInProgress() const override
{
- for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i)
+ for (uint8 i = 0; i < EncounterCount; ++i)
if (GetBossState(i) == IN_PROGRESS)
return true;
// Special state is set at Faction Champions after first champ dead, encounter is still in combat
- if (GetBossState(BOSS_CRUSADERS) == SPECIAL)
+ if (GetBossState(DATA_FACTION_CRUSADERS) == SPECIAL)
return true;
return false;
@@ -84,8 +127,8 @@ class instance_trial_of_the_crusader : public InstanceMapScript
player->SendUpdateWorldState(UPDATE_STATE_UI_SHOW, 0);
// make sure Anub'arak isnt missing
- if (GetBossState(BOSS_LICH_KING) == DONE && TrialCounter && GetBossState(BOSS_ANUBARAK) != DONE)
- if (!ObjectAccessor::GetCreature(*player, GetGuidData(NPC_ANUBARAK)))
+ if (GetBossState(DATA_LICH_KING) == DONE && TrialCounter && GetBossState(DATA_ANUBARAK) != DONE)
+ if (!GetCreature(DATA_ANUBARAK))
player->SummonCreature(NPC_ANUBARAK, AnubarakLoc[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME);
}
@@ -109,100 +152,18 @@ class instance_trial_of_the_crusader : public InstanceMapScript
void OnCreatureCreate(Creature* creature) override
{
- switch (creature->GetEntry())
- {
- case NPC_BARRENT:
- BarrentGUID = creature->GetGUID();
- if (!TrialCounter)
- creature->DespawnOrUnsummon();
- break;
- case NPC_TIRION:
- TirionGUID = creature->GetGUID();
- break;
- case NPC_TIRION_FORDRING:
- TirionFordringGUID = creature->GetGUID();
- break;
- case NPC_FIZZLEBANG:
- FizzlebangGUID = creature->GetGUID();
- break;
- case NPC_GARROSH:
- GarroshGUID = creature->GetGUID();
- break;
- case NPC_VARIAN:
- VarianGUID = creature->GetGUID();
- break;
-
- case NPC_GORMOK:
- GormokGUID = creature->GetGUID();
- break;
- case NPC_ACIDMAW:
- AcidmawGUID = creature->GetGUID();
- break;
- case NPC_DREADSCALE:
- DreadscaleGUID = creature->GetGUID();
- break;
- case NPC_ICEHOWL:
- IcehowlGUID = creature->GetGUID();
- break;
- case NPC_JARAXXUS:
- JaraxxusGUID = creature->GetGUID();
- break;
- case NPC_CHAMPIONS_CONTROLLER:
- ChampionsControllerGUID = creature->GetGUID();
- break;
- case NPC_DARKBANE:
- DarkbaneGUID = creature->GetGUID();
- break;
- case NPC_LIGHTBANE:
- LightbaneGUID = creature->GetGUID();
- break;
- case NPC_ANUBARAK:
- AnubarakGUID = creature->GetGUID();
- creature->SetRespawnDelay(7 * DAY);
- break;
- default:
- break;
- }
+ InstanceScript::OnCreatureCreate(creature);
+ if (creature->GetEntry() == NPC_BARRET_RAMSEY)
+ if (!TrialCounter)
+ creature->DespawnOrUnsummon();
}
void OnGameObjectCreate(GameObject* go) override
{
- switch (go->GetEntry())
- {
- case GO_CRUSADERS_CACHE_10:
- case GO_CRUSADERS_CACHE_25:
- case GO_CRUSADERS_CACHE_10_H:
- case GO_CRUSADERS_CACHE_25_H:
- CrusadersCacheGUID = go->GetGUID();
- break;
- case GO_ARGENT_COLISEUM_FLOOR:
- FloorGUID = go->GetGUID();
- if (GetBossState(BOSS_LICH_KING) == DONE)
- go->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED);
- break;
- case GO_MAIN_GATE_DOOR:
- MainGateDoorGUID = go->GetGUID();
- break;
- case GO_EAST_PORTCULLIS:
- EastPortcullisGUID = go->GetGUID();
- break;
- case GO_WEB_DOOR:
- WebDoorGUID = go->GetGUID();
- break;
-
- case GO_TRIBUTE_CHEST_10H_25:
- case GO_TRIBUTE_CHEST_10H_45:
- case GO_TRIBUTE_CHEST_10H_50:
- case GO_TRIBUTE_CHEST_10H_99:
- case GO_TRIBUTE_CHEST_25H_25:
- case GO_TRIBUTE_CHEST_25H_45:
- case GO_TRIBUTE_CHEST_25H_50:
- case GO_TRIBUTE_CHEST_25H_99:
- TributeChestGUID = go->GetGUID();
- break;
- default:
- break;
- }
+ InstanceScript::OnGameObjectCreate(go);
+ if (go->GetEntry() == GO_ARGENT_COLISEUM_FLOOR)
+ if (GetBossState(DATA_LICH_KING) == DONE)
+ go->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED);
}
void OnUnitDeath(Unit* unit) override
@@ -219,20 +180,20 @@ class instance_trial_of_the_crusader : public InstanceMapScript
switch (type)
{
- case BOSS_BEASTS:
+ case DATA_NORTHREND_BEASTS:
break;
- case BOSS_JARAXXUS:
+ case DATA_JARAXXUS:
// Cleanup Icehowl
- if (Creature* icehowl = instance->GetCreature(IcehowlGUID))
+ if (Creature* icehowl = GetCreature(DATA_ICEHOWL))
icehowl->DespawnOrUnsummon();
if (state == DONE)
EventStage = 2000;
break;
- case BOSS_CRUSADERS:
+ case DATA_FACTION_CRUSADERS:
// Cleanup Jaraxxus
- if (Creature* jaraxxus = instance->GetCreature(JaraxxusGUID))
+ if (Creature* jaraxxus = GetCreature(DATA_JARAXXUS))
jaraxxus->DespawnOrUnsummon();
- if (Creature* fizzlebang = instance->GetCreature(FizzlebangGUID))
+ if (Creature* fizzlebang = GetCreature(DATA_FIZZLEBANG))
fizzlebang->DespawnOrUnsummon();
switch (state)
{
@@ -247,8 +208,8 @@ class instance_trial_of_the_crusader : public InstanceMapScript
DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_DEFEAT_FACTION_CHAMPIONS);
if (ResilienceWillFixItTimer > 0)
DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_CHAMPIONS_KILLED_IN_MINUTE);
- DoRespawnGameObject(CrusadersCacheGUID, 7*DAY);
- if (GameObject* cache = instance->GetGameObject(CrusadersCacheGUID))
+ DoRespawnGameObject(GetGuidData(DATA_CRUSADERS_CHEST), 7*DAY);
+ if (GameObject* cache = GetGameObject(DATA_CRUSADERS_CHEST))
cache->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
EventStage = 3100;
break;
@@ -256,27 +217,27 @@ class instance_trial_of_the_crusader : public InstanceMapScript
break;
}
break;
- case BOSS_VALKIRIES:
+ case DATA_TWIN_VALKIRIES:
// Cleanup chest
- if (GameObject* cache = instance->GetGameObject(CrusadersCacheGUID))
+ if (GameObject* cache = GetGameObject(DATA_CRUSADERS_CHEST))
cache->Delete();
switch (state)
{
case FAIL:
- if (GetBossState(BOSS_VALKIRIES) == NOT_STARTED)
+ if (GetBossState(DATA_TWIN_VALKIRIES) == NOT_STARTED)
state = NOT_STARTED;
break;
case SPECIAL:
- if (GetBossState(BOSS_VALKIRIES) == SPECIAL)
+ if (GetBossState(DATA_TWIN_VALKIRIES) == SPECIAL)
state = DONE;
break;
default:
break;
}
break;
- case BOSS_LICH_KING:
+ case DATA_LICH_KING:
break;
- case BOSS_ANUBARAK:
+ case DATA_ANUBARAK:
switch (state)
{
case DONE:
@@ -319,7 +280,7 @@ class instance_trial_of_the_crusader : public InstanceMapScript
}
if (tributeChest)
- if (Creature* tirion = instance->GetCreature(TirionGUID))
+ if (Creature* tirion = GetCreature(DATA_FORDRING))
if (GameObject* chest = tirion->SummonGameObject(tributeChest, 805.62f, 134.87f, 142.16f, 3.27f, QuaternionData(), WEEK))
chest->SetRespawnTime(chest->GetRespawnDelay());
break;
@@ -334,16 +295,16 @@ class instance_trial_of_the_crusader : public InstanceMapScript
if (IsEncounterInProgress())
{
- CloseDoor(GetGuidData(GO_EAST_PORTCULLIS));
- CloseDoor(GetGuidData(GO_WEB_DOOR));
+ CloseDoor(GetGuidData(DATA_EAST_PORTCULLIS));
+ CloseDoor(GetGuidData(DATA_WEB_DOOR));
}
else
{
- OpenDoor(GetGuidData(GO_EAST_PORTCULLIS));
- OpenDoor(GetGuidData(GO_WEB_DOOR));
+ OpenDoor(GetGuidData(DATA_EAST_PORTCULLIS));
+ OpenDoor(GetGuidData(DATA_WEB_DOOR));
}
- if (type < MAX_ENCOUNTERS)
+ if (type < EncounterCount)
{
TC_LOG_DEBUG("scripts", "[ToCr] BossState(type %u) %u = state %u;", type, GetBossState(type), state);
if (state == FAIL)
@@ -360,21 +321,21 @@ class instance_trial_of_the_crusader : public InstanceMapScript
// if theres no more attemps allowed
if (!TrialCounter)
{
- if (Unit* announcer = instance->GetCreature(GetGuidData(NPC_BARRENT)))
+ if (Unit* announcer = GetCreature(DATA_BARRET_RAMSEY))
announcer->ToCreature()->DespawnOrUnsummon();
- if (Creature* anubArak = instance->GetCreature(GetGuidData(NPC_ANUBARAK)))
- anubArak->DespawnOrUnsummon();
+ if (Creature* anubarak = GetCreature(DATA_ANUBARAK))
+ anubarak->DespawnOrUnsummon();
}
}
NeedSave = true;
- EventStage = (type == BOSS_BEASTS ? 666 : 0);
+ EventStage = (type == DATA_NORTHREND_BEASTS ? 666 : 0);
state = NOT_STARTED;
}
if (state == DONE || NeedSave)
{
- if (Unit* announcer = instance->GetCreature(GetGuidData(NPC_BARRENT)))
+ if (Unit* announcer = GetCreature(DATA_BARRET_RAMSEY))
announcer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
Save();
}
@@ -421,10 +382,10 @@ class instance_trial_of_the_crusader : public InstanceMapScript
case ICEHOWL_DONE:
EventStage = 400;
SetData(TYPE_NORTHREND_BEASTS, DONE);
- SetBossState(BOSS_BEASTS, DONE);
+ SetBossState(DATA_NORTHREND_BEASTS, DONE);
break;
case FAIL:
- SetBossState(BOSS_BEASTS, FAIL);
+ SetBossState(DATA_NORTHREND_BEASTS, FAIL);
break;
default:
break;
@@ -448,57 +409,6 @@ class instance_trial_of_the_crusader : public InstanceMapScript
}
}
- ObjectGuid GetGuidData(uint32 type) const override
- {
- switch (type)
- {
- case NPC_BARRENT:
- return BarrentGUID;
- case NPC_TIRION:
- return TirionGUID;
- case NPC_TIRION_FORDRING:
- return TirionFordringGUID;
- case NPC_FIZZLEBANG:
- return FizzlebangGUID;
- case NPC_GARROSH:
- return GarroshGUID;
- case NPC_VARIAN:
- return VarianGUID;
-
- case NPC_GORMOK:
- return GormokGUID;
- case NPC_ACIDMAW:
- return AcidmawGUID;
- case NPC_DREADSCALE:
- return DreadscaleGUID;
- case NPC_ICEHOWL:
- return IcehowlGUID;
- case NPC_JARAXXUS:
- return JaraxxusGUID;
- case NPC_CHAMPIONS_CONTROLLER:
- return ChampionsControllerGUID;
- case NPC_DARKBANE:
- return DarkbaneGUID;
- case NPC_LIGHTBANE:
- return LightbaneGUID;
- case NPC_ANUBARAK:
- return AnubarakGUID;
-
- case GO_ARGENT_COLISEUM_FLOOR:
- return FloorGUID;
- case GO_MAIN_GATE_DOOR:
- return MainGateDoorGUID;
- case GO_EAST_PORTCULLIS:
- return EastPortcullisGUID;
- case GO_WEB_DOOR:
- return WebDoorGUID;
- default:
- break;
- }
-
- return ObjectGuid::Empty;
- }
-
uint32 GetData(uint32 type) const override
{
switch (type)
@@ -553,7 +463,7 @@ class instance_trial_of_the_crusader : public InstanceMapScript
case 6000:
case 6005:
case 6010:
- return NPC_TIRION;
+ return NPC_TIRION_FORDRING;
break;
case 5010:
case 5030:
@@ -595,7 +505,7 @@ class instance_trial_of_the_crusader : public InstanceMapScript
return NPC_FIZZLEBANG;
break;
default:
- return NPC_TIRION;
+ return NPC_TIRION_FORDRING;
break;
};
default:
@@ -615,7 +525,7 @@ class instance_trial_of_the_crusader : public InstanceMapScript
NotOneButTwoJormungarsTimer -= diff;
}
- if (GetBossState(BOSS_CRUSADERS) == SPECIAL && ResilienceWillFixItTimer)
+ if (GetBossState(DATA_FACTION_CRUSADERS) == SPECIAL && ResilienceWillFixItTimer)
{
if (ResilienceWillFixItTimer <= diff)
ResilienceWillFixItTimer = 0;
@@ -630,7 +540,7 @@ class instance_trial_of_the_crusader : public InstanceMapScript
std::ostringstream saveStream;
- for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i)
+ for (uint8 i = 0; i < EncounterCount; ++i)
saveStream << GetBossState(i) << ' ';
saveStream << TrialCounter;
@@ -658,7 +568,7 @@ class instance_trial_of_the_crusader : public InstanceMapScript
std::istringstream loadStream(strIn);
- for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i)
+ for (uint8 i = 0; i < EncounterCount; ++i)
{
uint32 tmpState;
loadStream >> tmpState;
@@ -718,30 +628,6 @@ class instance_trial_of_the_crusader : public InstanceMapScript
bool NeedSave;
std::string SaveDataBuffer;
- ObjectGuid BarrentGUID;
- ObjectGuid TirionGUID;
- ObjectGuid TirionFordringGUID;
- ObjectGuid FizzlebangGUID;
- ObjectGuid GarroshGUID;
- ObjectGuid VarianGUID;
-
- ObjectGuid GormokGUID;
- ObjectGuid AcidmawGUID;
- ObjectGuid DreadscaleGUID;
- ObjectGuid IcehowlGUID;
- ObjectGuid JaraxxusGUID;
- ObjectGuid ChampionsControllerGUID;
- ObjectGuid DarkbaneGUID;
- ObjectGuid LightbaneGUID;
- ObjectGuid AnubarakGUID;
-
- ObjectGuid CrusadersCacheGUID;
- ObjectGuid FloorGUID;
- ObjectGuid TributeChestGUID;
- ObjectGuid MainGateDoorGUID;
- ObjectGuid EastPortcullisGUID;
- ObjectGuid WebDoorGUID;
-
// Achievement stuff
uint32 NotOneButTwoJormungarsTimer;
uint32 ResilienceWillFixItTimer;
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp
index fdc93f56c39..de24ab4a352 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp
@@ -164,12 +164,12 @@ struct _Messages
static _Messages _GossipMessage[]=
{
- {MSG_BEASTS, GOSSIP_ACTION_INFO_DEF + 1, false, BOSS_BEASTS},
- {MSG_JARAXXUS, GOSSIP_ACTION_INFO_DEF + 2, false, BOSS_JARAXXUS},
- {MSG_CRUSADERS, GOSSIP_ACTION_INFO_DEF + 3, false, BOSS_CRUSADERS},
- {MSG_VALKIRIES, GOSSIP_ACTION_INFO_DEF + 4, false, BOSS_VALKIRIES},
- {MSG_LICH_KING, GOSSIP_ACTION_INFO_DEF + 5, false, BOSS_ANUBARAK},
- {MSG_ANUBARAK, GOSSIP_ACTION_INFO_DEF + 6, true, BOSS_ANUBARAK}
+ {MSG_BEASTS, GOSSIP_ACTION_INFO_DEF + 1, false, DATA_NORTHREND_BEASTS},
+ {MSG_JARAXXUS, GOSSIP_ACTION_INFO_DEF + 2, false, DATA_JARAXXUS},
+ {MSG_CRUSADERS, GOSSIP_ACTION_INFO_DEF + 3, false, DATA_FACTION_CRUSADERS},
+ {MSG_VALKIRIES, GOSSIP_ACTION_INFO_DEF + 4, false, DATA_TWIN_VALKIRIES},
+ {MSG_LICH_KING, GOSSIP_ACTION_INFO_DEF + 5, false, DATA_ANUBARAK},
+ {MSG_ANUBARAK, GOSSIP_ACTION_INFO_DEF + 6, true, DATA_ANUBARAK}
};
enum Messages
@@ -229,16 +229,16 @@ class npc_announcer_toc10 : public CreatureScript
ClearGossipMenuFor(player);
CloseGossipMenuFor(player);
- if (instance->GetBossState(BOSS_BEASTS) != DONE)
+ if (instance->GetBossState(DATA_NORTHREND_BEASTS) != DONE)
{
instance->SetData(TYPE_EVENT, 110);
instance->SetData(TYPE_NORTHREND_BEASTS, NOT_STARTED);
- instance->SetBossState(BOSS_BEASTS, NOT_STARTED);
+ instance->SetBossState(DATA_NORTHREND_BEASTS, NOT_STARTED);
}
- else if (instance->GetBossState(BOSS_JARAXXUS) != DONE)
+ else if (instance->GetBossState(DATA_JARAXXUS) != DONE)
{
// if Jaraxxus is spawned, but the raid wiped
- if (Creature* jaraxxus = ObjectAccessor::GetCreature(*player, instance->GetGuidData(NPC_JARAXXUS)))
+ if (Creature* jaraxxus = instance->GetCreature(DATA_JARAXXUS))
{
jaraxxus->RemoveAurasDueToSpell(SPELL_JARAXXUS_CHAINS);
jaraxxus->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
@@ -249,29 +249,29 @@ class npc_announcer_toc10 : public CreatureScript
else
{
instance->SetData(TYPE_EVENT, 1010);
- instance->SetBossState(BOSS_JARAXXUS, NOT_STARTED);
+ instance->SetBossState(DATA_JARAXXUS, NOT_STARTED);
}
}
- else if (instance->GetBossState(BOSS_CRUSADERS) != DONE)
+ else if (instance->GetBossState(DATA_FACTION_CRUSADERS) != DONE)
{
if (player->GetTeam() == ALLIANCE)
instance->SetData(TYPE_EVENT, 3000);
else
instance->SetData(TYPE_EVENT, 3001);
- instance->SetBossState(BOSS_CRUSADERS, NOT_STARTED);
+ instance->SetBossState(DATA_FACTION_CRUSADERS, NOT_STARTED);
}
- else if (instance->GetBossState(BOSS_VALKIRIES) != DONE)
+ else if (instance->GetBossState(DATA_TWIN_VALKIRIES) != DONE)
{
instance->SetData(TYPE_EVENT, 4000);
- instance->SetBossState(BOSS_VALKIRIES, NOT_STARTED);
+ instance->SetBossState(DATA_TWIN_VALKIRIES, NOT_STARTED);
}
- else if (instance->GetBossState(BOSS_LICH_KING) != DONE)
+ else if (instance->GetBossState(DATA_LICH_KING) != DONE)
{
if (me->GetMap()->GetPlayers().getFirst()->GetSource()->GetTeam() == ALLIANCE)
instance->SetData(TYPE_EVENT, 4020);
else
instance->SetData(TYPE_EVENT, 4030);
- instance->SetBossState(BOSS_LICH_KING, NOT_STARTED);
+ instance->SetBossState(DATA_LICH_KING, NOT_STARTED);
}
me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
return true;
@@ -305,7 +305,7 @@ class boss_lich_king_toc : public CreatureScript
summoned->SetDisplayId(summoned->GetCreatureTemplate()->Modelid2);
}
- _instance->SetBossState(BOSS_LICH_KING, IN_PROGRESS);
+ _instance->SetBossState(DATA_LICH_KING, IN_PROGRESS);
me->SetWalk(true);
}
@@ -376,15 +376,15 @@ class boss_lich_king_toc : public CreatureScript
break;
case 5080:
{
- if (GameObject* go = ObjectAccessor::GetGameObject(*me, _instance->GetGuidData(GO_ARGENT_COLISEUM_FLOOR)))
+ if (GameObject* go = _instance->GetGameObject(DATA_COLISEUM_FLOOR))
go->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED);
me->CastSpell(me, SPELL_CORPSE_TELEPORT, false);
me->CastSpell(me, SPELL_DESTROY_FLOOR_KNOCKUP, false);
- _instance->SetBossState(BOSS_LICH_KING, DONE);
+ _instance->SetBossState(DATA_LICH_KING, DONE);
- if (!ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_ANUBARAK)))
+ if (!_instance->GetCreature(DATA_ANUBARAK))
me->SummonCreature(NPC_ANUBARAK, AnubarakLoc[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME);
_instance->SetData(TYPE_EVENT, 0);
@@ -429,7 +429,7 @@ class npc_fizzlebang_toc : public CreatureScript
{
Talk(SAY_STAGE_1_06, killer);
_instance->SetData(TYPE_EVENT, 1180);
- if (Creature* jaraxxus = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_JARAXXUS)))
+ if (Creature* jaraxxus = _instance->GetCreature(DATA_JARAXXUS))
{
jaraxxus->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
jaraxxus->SetImmuneToPC(false);
@@ -454,7 +454,7 @@ class npc_fizzlebang_toc : public CreatureScript
{
case 1:
me->SetWalk(false);
- _instance->DoUseDoorOrButton(_instance->GetGuidData(GO_MAIN_GATE_DOOR));
+ _instance->DoUseDoorOrButton(_instance->GetGuidData(DATA_MAIN_GATE));
_instance->SetData(TYPE_EVENT, 1120);
_instance->SetData(TYPE_EVENT_TIMER, 1*IN_MILLISECONDS);
break;
@@ -538,7 +538,7 @@ class npc_fizzlebang_toc : public CreatureScript
_updateTimer = 5*IN_MILLISECONDS;
break;
case 1142:
- if (Creature* jaraxxus = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_JARAXXUS)))
+ if (Creature* jaraxxus = _instance->GetCreature(DATA_JARAXXUS))
jaraxxus->SetTarget(me->GetGUID());
if (Creature* pTrigger = ObjectAccessor::GetCreature(*me, _triggerGUID))
pTrigger->DespawnOrUnsummon();
@@ -548,13 +548,13 @@ class npc_fizzlebang_toc : public CreatureScript
_updateTimer = 10*IN_MILLISECONDS;
break;
case 1144:
- if (Creature* jaraxxus = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_JARAXXUS)))
+ if (Creature* jaraxxus = _instance->GetCreature(DATA_JARAXXUS))
jaraxxus->AI()->Talk(SAY_STAGE_1_05);
_instance->SetData(TYPE_EVENT, 1150);
_updateTimer = 5*IN_MILLISECONDS;
break;
case 1150:
- if (Creature* jaraxxus = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_JARAXXUS)))
+ if (Creature* jaraxxus = _instance->GetCreature(DATA_JARAXXUS))
{
//1-shot Fizzlebang
jaraxxus->CastSpell(me, 67888, false); // 67888 - Fel Lightning
@@ -605,7 +605,7 @@ class npc_tirion_toc : public CreatureScript
if (!_instance)
return;
- if (_instance->GetData(TYPE_EVENT_NPC) != NPC_TIRION)
+ if (_instance->GetData(TYPE_EVENT_NPC) != NPC_TIRION_FORDRING)
return;
uint32 _updateTimer = _instance->GetData(TYPE_EVENT_TIMER);
@@ -627,9 +627,9 @@ class npc_tirion_toc : public CreatureScript
break;
case 150:
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE);
- if (_instance->GetBossState(BOSS_BEASTS) != DONE)
+ if (_instance->GetBossState(DATA_NORTHREND_BEASTS) != DONE)
{
- _instance->DoUseDoorOrButton(_instance->GetGuidData(GO_MAIN_GATE_DOOR));
+ _instance->DoUseDoorOrButton(_instance->GetGuidData(DATA_MAIN_GATE));
if (Creature* gormok = me->SummonCreature(NPC_GORMOK, ToCSpawnLoc[0].GetPositionX(), ToCSpawnLoc[0].GetPositionY(), ToCSpawnLoc[0].GetPositionZ(), 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30*IN_MILLISECONDS))
{
@@ -649,9 +649,9 @@ class npc_tirion_toc : public CreatureScript
break;
case 200:
Talk(SAY_STAGE_0_04);
- if (_instance->GetBossState(BOSS_BEASTS) != DONE)
+ if (_instance->GetBossState(DATA_NORTHREND_BEASTS) != DONE)
{
- _instance->DoUseDoorOrButton(_instance->GetGuidData(GO_MAIN_GATE_DOOR));
+ _instance->DoUseDoorOrButton(_instance->GetGuidData(DATA_MAIN_GATE));
if (Creature* dreadscale = me->SummonCreature(NPC_DREADSCALE, ToCSpawnLoc[1].GetPositionX(), ToCSpawnLoc[1].GetPositionY(), ToCSpawnLoc[1].GetPositionZ(), 5, TEMPSUMMON_MANUAL_DESPAWN))
{
dreadscale->GetMotionMaster()->MovePoint(0, ToCCommonLoc[5].GetPositionX(), ToCCommonLoc[5].GetPositionY(), ToCCommonLoc[5].GetPositionZ());
@@ -667,9 +667,9 @@ class npc_tirion_toc : public CreatureScript
break;
case 300:
Talk(SAY_STAGE_0_05);
- if (_instance->GetBossState(BOSS_BEASTS) != DONE)
+ if (_instance->GetBossState(DATA_NORTHREND_BEASTS) != DONE)
{
- _instance->DoUseDoorOrButton(_instance->GetGuidData(GO_MAIN_GATE_DOOR));
+ _instance->DoUseDoorOrButton(_instance->GetGuidData(DATA_MAIN_GATE));
if (Creature* icehowl = me->SummonCreature(NPC_ICEHOWL, ToCSpawnLoc[0].GetPositionX(), ToCSpawnLoc[0].GetPositionY(), ToCSpawnLoc[0].GetPositionZ(), 5, TEMPSUMMON_DEAD_DESPAWN))
{
icehowl->GetMotionMaster()->MovePoint(2, ToCCommonLoc[5].GetPositionX(), ToCCommonLoc[5].GetPositionY(), ToCCommonLoc[5].GetPositionZ());
@@ -697,7 +697,7 @@ class npc_tirion_toc : public CreatureScript
case 1010:
Talk(SAY_STAGE_1_01);
_updateTimer = 7*IN_MILLISECONDS;
- _instance->DoUseDoorOrButton(_instance->GetGuidData(GO_MAIN_GATE_DOOR));
+ _instance->DoUseDoorOrButton(_instance->GetGuidData(DATA_MAIN_GATE));
me->SummonCreature(NPC_FIZZLEBANG, ToCSpawnLoc[0].GetPositionX(), ToCSpawnLoc[0].GetPositionY(), ToCSpawnLoc[0].GetPositionZ(), 2, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME);
_instance->SetData(TYPE_EVENT, 0);
break;
@@ -751,7 +751,7 @@ class npc_tirion_toc : public CreatureScript
_instance->SetData(TYPE_EVENT, 3092);
break;
case 3092:
- if (Creature* pChampionController = ObjectAccessor::GetCreature((*me), _instance->GetGuidData(NPC_CHAMPIONS_CONTROLLER)))
+ if (Creature* pChampionController = _instance->GetCreature(DATA_FACTION_CRUSADERS))
pChampionController->AI()->SetData(1, NOT_STARTED);
_instance->SetData(TYPE_EVENT, 3095);
break;
@@ -768,14 +768,14 @@ class npc_tirion_toc : public CreatureScript
break;
case 4010:
Talk(SAY_STAGE_3_02);
- if (Creature* lightbane = me->SummonCreature(NPC_LIGHTBANE, ToCSpawnLoc[1].GetPositionX(), ToCSpawnLoc[1].GetPositionY(), ToCSpawnLoc[1].GetPositionZ(), 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME))
+ if (Creature* lightbane = me->SummonCreature(NPC_FJOLA_LIGHTBANE, ToCSpawnLoc[1].GetPositionX(), ToCSpawnLoc[1].GetPositionY(), ToCSpawnLoc[1].GetPositionZ(), 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME))
{
lightbane->SetVisible(false);
lightbane->SetReactState(REACT_PASSIVE);
lightbane->SummonCreature(NPC_LIGHT_ESSENCE, TwinValkyrsLoc[0].GetPositionX(), TwinValkyrsLoc[0].GetPositionY(), TwinValkyrsLoc[0].GetPositionZ());
lightbane->SummonCreature(NPC_LIGHT_ESSENCE, TwinValkyrsLoc[1].GetPositionX(), TwinValkyrsLoc[1].GetPositionY(), TwinValkyrsLoc[1].GetPositionZ());
}
- if (Creature* darkbane = me->SummonCreature(NPC_DARKBANE, ToCSpawnLoc[2].GetPositionX(), ToCSpawnLoc[2].GetPositionY(), ToCSpawnLoc[2].GetPositionZ(), 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME))
+ if (Creature* darkbane = me->SummonCreature(NPC_EYDIS_DARKBANE, ToCSpawnLoc[2].GetPositionX(), ToCSpawnLoc[2].GetPositionY(), ToCSpawnLoc[2].GetPositionZ(), 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME))
{
darkbane->SetVisible(false);
darkbane->SetReactState(REACT_PASSIVE);
@@ -786,13 +786,13 @@ class npc_tirion_toc : public CreatureScript
_instance->SetData(TYPE_EVENT, 4015);
break;
case 4015:
- _instance->DoUseDoorOrButton(_instance->GetGuidData(GO_MAIN_GATE_DOOR));
- if (Creature* lightbane = ObjectAccessor::GetCreature((*me), _instance->GetGuidData(NPC_LIGHTBANE)))
+ _instance->DoUseDoorOrButton(_instance->GetGuidData(DATA_MAIN_GATE));
+ if (Creature* lightbane = _instance->GetCreature(DATA_FJOLA_LIGHTBANE))
{
lightbane->GetMotionMaster()->MovePoint(1, ToCCommonLoc[8].GetPositionX(), ToCCommonLoc[8].GetPositionY(), ToCCommonLoc[8].GetPositionZ());
lightbane->SetVisible(true);
}
- if (Creature* darkbane = ObjectAccessor::GetCreature((*me), _instance->GetGuidData(NPC_DARKBANE)))
+ if (Creature* darkbane = _instance->GetCreature(DATA_EYDIS_DARKBANE))
{
darkbane->GetMotionMaster()->MovePoint(1, ToCCommonLoc[9].GetPositionX(), ToCCommonLoc[9].GetPositionY(), ToCCommonLoc[9].GetPositionZ());
darkbane->SetVisible(true);
@@ -801,7 +801,7 @@ class npc_tirion_toc : public CreatureScript
_instance->SetData(TYPE_EVENT, 4016);
break;
case 4016:
- _instance->DoUseDoorOrButton(_instance->GetGuidData(GO_MAIN_GATE_DOOR));
+ _instance->DoUseDoorOrButton(_instance->GetGuidData(DATA_MAIN_GATE));
_instance->SetData(TYPE_EVENT, 4017);
break;
case 4040:
@@ -824,14 +824,14 @@ class npc_tirion_toc : public CreatureScript
_instance->SetData(TYPE_EVENT, 0);
break;
case 6000:
- me->SummonCreature(NPC_TIRION_FORDRING, EndSpawnLoc[0]);
+ me->SummonCreature(NPC_TIRION_FORDRING_ANUBARAK, EndSpawnLoc[0]);
me->SummonCreature(NPC_ARGENT_MAGE, EndSpawnLoc[1]);
me->SummonGameObject(GO_PORTAL_TO_DALARAN, EndSpawnLoc[2], QuaternionData(), 0);
_updateTimer = 20*IN_MILLISECONDS;
_instance->SetData(TYPE_EVENT, 6005);
break;
case 6005:
- if (Creature* tirionFordring = ObjectAccessor::GetCreature((*me), _instance->GetGuidData(NPC_TIRION_FORDRING)))
+ if (Creature* tirionFordring = _instance->GetCreature(DATA_FORDRING_ANUBARAK))
tirionFordring->AI()->Talk(SAY_STAGE_4_06);
_updateTimer = 20*IN_MILLISECONDS;
_instance->SetData(TYPE_EVENT, 6010);
@@ -839,10 +839,10 @@ class npc_tirion_toc : public CreatureScript
case 6010:
if (IsHeroic())
{
- if (Creature* tirionFordring = ObjectAccessor::GetCreature((*me), _instance->GetGuidData(NPC_TIRION_FORDRING)))
+ if (Creature* tirionFordring = _instance->GetCreature(DATA_FORDRING_ANUBARAK))
tirionFordring->AI()->Talk(SAY_STAGE_4_07);
_updateTimer = 1*MINUTE*IN_MILLISECONDS;
- _instance->SetBossState(BOSS_ANUBARAK, SPECIAL);
+ _instance->SetBossState(DATA_ANUBARAK, SPECIAL);
_instance->SetData(TYPE_EVENT, 6020);
}
else
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h
index d744c7e1cd2..d3565fe27eb 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h
@@ -25,19 +25,42 @@
#define DataHeader "TCR"
struct Position;
+uint32 const EncounterCount = 6;
enum TCRDataTypes
{
- BOSS_BEASTS = 0,
- BOSS_JARAXXUS = 1,
- BOSS_CRUSADERS = 2,
- BOSS_VALKIRIES = 3,
- BOSS_LICH_KING = 4, // not really a boss but oh well
- BOSS_ANUBARAK = 5,
- MAX_ENCOUNTERS = 6,
-
- TYPE_COUNTER = 8,
- TYPE_EVENT = 9,
+ // Encounter States
+ DATA_NORTHREND_BEASTS = 0,
+ DATA_JARAXXUS = 1,
+ DATA_FACTION_CRUSADERS = 2,
+ DATA_TWIN_VALKIRIES = 3,
+ DATA_LICH_KING = 4,
+ DATA_ANUBARAK = 5,
+
+ // Additional Data
+ DATA_GORMOK_THE_IMPALER = 5,
+ DATA_ACIDMAW = 6,
+ DATA_DREADSCALE = 7,
+ DATA_ICEHOWL = 8,
+ DATA_FJOLA_LIGHTBANE = 9,
+ DATA_EYDIS_DARKBANE = 10,
+ DATA_BARRET_RAMSEY = 11,
+ DATA_FORDRING = 12,
+ DATA_FORDRING_ANUBARAK = 13,
+ DATA_VARIAN = 14,
+ DATA_GARROSH = 15,
+ DATA_FIZZLEBANG = 16,
+ DATA_FACTION_CHAMPIONS = 17,
+
+ DATA_CRUSADERS_CHEST = 18,
+ DATA_COLISEUM_FLOOR = 19,
+ DATA_MAIN_GATE = 20,
+ DATA_EAST_PORTCULLIS = 21,
+ DATA_WEB_DOOR = 22,
+ DATA_TRIBUTE_CHEST = 23,
+
+ TYPE_COUNTER = 24,
+ TYPE_EVENT = 25,
TYPE_EVENT_TIMER = 101,
TYPE_EVENT_NPC = 102,
@@ -60,7 +83,7 @@ enum TCRSpellIds
enum TCRMiscData
{
- DESPAWN_TIME = 1200000
+ DESPAWN_TIME = 1200000
};
extern Position const ToCCommonLoc[];
@@ -68,121 +91,121 @@ extern Position const AnubarakLoc[];
enum TCRWorldStateIds
{
- UPDATE_STATE_UI_SHOW = 4390,
- UPDATE_STATE_UI_COUNT = 4389
+ UPDATE_STATE_UI_SHOW = 4390,
+ UPDATE_STATE_UI_COUNT = 4389
};
enum NorthrendBeasts
{
- GORMOK_IN_PROGRESS = 1000,
- GORMOK_DONE = 1001,
- SNAKES_IN_PROGRESS = 2000,
- DREADSCALE_SUBMERGED = 2001,
- ACIDMAW_SUBMERGED = 2002,
- SNAKES_SPECIAL = 2003,
- SNAKES_DONE = 2004,
- ICEHOWL_IN_PROGRESS = 3000,
- ICEHOWL_DONE = 3001
+ GORMOK_IN_PROGRESS = 1000,
+ GORMOK_DONE = 1001,
+ SNAKES_IN_PROGRESS = 2000,
+ DREADSCALE_SUBMERGED = 2001,
+ ACIDMAW_SUBMERGED = 2002,
+ SNAKES_SPECIAL = 2003,
+ SNAKES_DONE = 2004,
+ ICEHOWL_IN_PROGRESS = 3000,
+ ICEHOWL_DONE = 3001
};
enum AnnouncerMessages
{
- MSG_BEASTS = 724001,
- MSG_JARAXXUS = 724002,
- MSG_CRUSADERS = 724003,
- MSG_VALKIRIES = 724004,
- MSG_LICH_KING = 724005,
- MSG_ANUBARAK = 724006
+ MSG_BEASTS = 724001,
+ MSG_JARAXXUS = 724002,
+ MSG_CRUSADERS = 724003,
+ MSG_VALKIRIES = 724004,
+ MSG_LICH_KING = 724005,
+ MSG_ANUBARAK = 724006
};
enum TCRCreatureIds
{
- NPC_BARRENT = 34816,
- NPC_TIRION = 34996,
- NPC_TIRION_FORDRING = 36095,
- NPC_ARGENT_MAGE = 36097,
- NPC_FIZZLEBANG = 35458,
- NPC_GARROSH = 34995,
- NPC_VARIAN = 34990,
- NPC_LICH_KING = 35877,
-
- NPC_THRALL = 34994,
- NPC_PROUDMOORE = 34992,
- NPC_WILFRED_PORTAL = 17965,
- NPC_TRIGGER = 35651,
-
- NPC_ICEHOWL = 34797,
- NPC_GORMOK = 34796,
- NPC_DREADSCALE = 34799,
- NPC_ACIDMAW = 35144,
-
- NPC_JARAXXUS = 34780,
-
- NPC_CHAMPIONS_CONTROLLER = 34781,
-
- NPC_ALLIANCE_DEATH_KNIGHT = 34461,
- NPC_ALLIANCE_DRUID_BALANCE = 34460,
- NPC_ALLIANCE_DRUID_RESTORATION = 34469,
- NPC_ALLIANCE_HUNTER = 34467,
- NPC_ALLIANCE_MAGE = 34468,
- NPC_ALLIANCE_PALADIN_HOLY = 34465,
- NPC_ALLIANCE_PALADIN_RETRIBUTION = 34471,
- NPC_ALLIANCE_PRIEST_DISCIPLINE = 34466,
- NPC_ALLIANCE_PRIEST_SHADOW = 34473,
- NPC_ALLIANCE_ROGUE = 34472,
- NPC_ALLIANCE_SHAMAN_ENHANCEMENT = 34463,
- NPC_ALLIANCE_SHAMAN_RESTORATION = 34470,
- NPC_ALLIANCE_WARLOCK = 34474,
- NPC_ALLIANCE_WARRIOR = 34475,
-
- NPC_HORDE_DEATH_KNIGHT = 34458,
- NPC_HORDE_DRUID_BALANCE = 34451,
- NPC_HORDE_DRUID_RESTORATION = 34459,
- NPC_HORDE_HUNTER = 34448,
- NPC_HORDE_MAGE = 34449,
- NPC_HORDE_PALADIN_HOLY = 34445,
- NPC_HORDE_PALADIN_RETRIBUTION = 34456,
- NPC_HORDE_PRIEST_DISCIPLINE = 34447,
- NPC_HORDE_PRIEST_SHADOW = 34441,
- NPC_HORDE_ROGUE = 34454,
- NPC_HORDE_SHAMAN_ENHANCEMENT = 34455,
- NPC_HORDE_SHAMAN_RESTORATION = 34444,
- NPC_HORDE_WARLOCK = 34450,
- NPC_HORDE_WARRIOR = 34453,
-
- NPC_LIGHTBANE = 34497,
- NPC_DARKBANE = 34496,
-
- NPC_DARK_ESSENCE = 34567,
- NPC_LIGHT_ESSENCE = 34568,
-
- NPC_ANUBARAK = 34564
+ NPC_BARRET_RAMSEY = 34816,
+ NPC_TIRION_FORDRING = 34996,
+ NPC_TIRION_FORDRING_ANUBARAK = 36095,
+ NPC_ARGENT_MAGE = 36097,
+ NPC_FIZZLEBANG = 35458,
+ NPC_GARROSH = 34995,
+ NPC_VARIAN = 34990,
+ NPC_LICH_KING = 35877,
+
+ NPC_THRALL = 34994,
+ NPC_PROUDMOORE = 34992,
+ NPC_WILFRED_PORTAL = 17965,
+ NPC_TRIGGER = 35651,
+
+ NPC_ICEHOWL = 34797,
+ NPC_GORMOK = 34796,
+ NPC_DREADSCALE = 34799,
+ NPC_ACIDMAW = 35144,
+
+ NPC_JARAXXUS = 34780,
+
+ NPC_CHAMPIONS_CONTROLLER = 34781,
+
+ NPC_ALLIANCE_DEATH_KNIGHT = 34461,
+ NPC_ALLIANCE_DRUID_BALANCE = 34460,
+ NPC_ALLIANCE_DRUID_RESTORATION = 34469,
+ NPC_ALLIANCE_HUNTER = 34467,
+ NPC_ALLIANCE_MAGE = 34468,
+ NPC_ALLIANCE_PALADIN_HOLY = 34465,
+ NPC_ALLIANCE_PALADIN_RETRIBUTION = 34471,
+ NPC_ALLIANCE_PRIEST_DISCIPLINE = 34466,
+ NPC_ALLIANCE_PRIEST_SHADOW = 34473,
+ NPC_ALLIANCE_ROGUE = 34472,
+ NPC_ALLIANCE_SHAMAN_ENHANCEMENT = 34463,
+ NPC_ALLIANCE_SHAMAN_RESTORATION = 34470,
+ NPC_ALLIANCE_WARLOCK = 34474,
+ NPC_ALLIANCE_WARRIOR = 34475,
+
+ NPC_HORDE_DEATH_KNIGHT = 34458,
+ NPC_HORDE_DRUID_BALANCE = 34451,
+ NPC_HORDE_DRUID_RESTORATION = 34459,
+ NPC_HORDE_HUNTER = 34448,
+ NPC_HORDE_MAGE = 34449,
+ NPC_HORDE_PALADIN_HOLY = 34445,
+ NPC_HORDE_PALADIN_RETRIBUTION = 34456,
+ NPC_HORDE_PRIEST_DISCIPLINE = 34447,
+ NPC_HORDE_PRIEST_SHADOW = 34441,
+ NPC_HORDE_ROGUE = 34454,
+ NPC_HORDE_SHAMAN_ENHANCEMENT = 34455,
+ NPC_HORDE_SHAMAN_RESTORATION = 34444,
+ NPC_HORDE_WARLOCK = 34450,
+ NPC_HORDE_WARRIOR = 34453,
+
+ NPC_FJOLA_LIGHTBANE = 34497,
+ NPC_EYDIS_DARKBANE = 34496,
+
+ NPC_DARK_ESSENCE = 34567,
+ NPC_LIGHT_ESSENCE = 34568,
+
+ NPC_ANUBARAK = 34564
};
enum TCRGameObjectIds
{
- GO_CRUSADERS_CACHE_10 = 195631,
- GO_CRUSADERS_CACHE_25 = 195632,
- GO_CRUSADERS_CACHE_10_H = 195633,
- GO_CRUSADERS_CACHE_25_H = 195635,
+ GO_CRUSADERS_CACHE_10 = 195631,
+ GO_CRUSADERS_CACHE_25 = 195632,
+ GO_CRUSADERS_CACHE_10_H = 195633,
+ GO_CRUSADERS_CACHE_25_H = 195635,
// Tribute Chest (heroic)
// 10-man modes
- GO_TRIBUTE_CHEST_10H_25 = 195668, // 10man 01-24 attempts
- GO_TRIBUTE_CHEST_10H_45 = 195667, // 10man 25-44 attempts
- GO_TRIBUTE_CHEST_10H_50 = 195666, // 10man 45-49 attempts
- GO_TRIBUTE_CHEST_10H_99 = 195665, // 10man 50 attempts
+ GO_TRIBUTE_CHEST_10H_25 = 195668, // 10man 01-24 attempts
+ GO_TRIBUTE_CHEST_10H_45 = 195667, // 10man 25-44 attempts
+ GO_TRIBUTE_CHEST_10H_50 = 195666, // 10man 45-49 attempts
+ GO_TRIBUTE_CHEST_10H_99 = 195665, // 10man 50 attempts
// 25-man modes
- GO_TRIBUTE_CHEST_25H_25 = 195672, // 25man 01-24 attempts
- GO_TRIBUTE_CHEST_25H_45 = 195671, // 25man 25-44 attempts
- GO_TRIBUTE_CHEST_25H_50 = 195670, // 25man 45-49 attempts
- GO_TRIBUTE_CHEST_25H_99 = 195669, // 25man 50 attempts
-
- GO_ARGENT_COLISEUM_FLOOR = 195527, //20943
- GO_MAIN_GATE_DOOR = 195647,
- GO_EAST_PORTCULLIS = 195648,
- GO_WEB_DOOR = 195485,
- GO_PORTAL_TO_DALARAN = 195682
+ GO_TRIBUTE_CHEST_25H_25 = 195672, // 25man 01-24 attempts
+ GO_TRIBUTE_CHEST_25H_45 = 195671, // 25man 25-44 attempts
+ GO_TRIBUTE_CHEST_25H_50 = 195670, // 25man 45-49 attempts
+ GO_TRIBUTE_CHEST_25H_99 = 195669, // 25man 50 attempts
+
+ GO_ARGENT_COLISEUM_FLOOR = 195527, //20943
+ GO_MAIN_GATE_DOOR = 195647,
+ GO_EAST_PORTCULLIS = 195648,
+ GO_WEB_DOOR = 195485,
+ GO_PORTAL_TO_DALARAN = 195682
};
enum TCRAchievementData
diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp
index 2bcfd7a70d6..bbfc6ac0924 100644
--- a/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp
+++ b/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp
@@ -243,7 +243,7 @@ public:
if (Creature* crystalChannelTarget = crystal->FindNearestCreature(NPC_CRYSTAL_CHANNEL_TARGET, 5.0f))
{
if (active)
- crystalChannelTarget->CastSpell((Unit*)nullptr, SPELL_BEAM_CHANNEL);
+ crystalChannelTarget->CastSpell(nullptr, SPELL_BEAM_CHANNEL);
else if (crystalChannelTarget->HasUnitState(UNIT_STATE_CASTING))
crystalChannelTarget->CastStop();
}
@@ -384,7 +384,7 @@ class spell_novos_summon_minions : public SpellScriptLoader
void HandleScript(SpellEffIndex /*effIndex*/)
{
for (uint8 i = 0; i < 2; ++i)
- GetCaster()->CastSpell((Unit*)nullptr, SPELL_SUMMON_COPY_OF_MINIONS, true);
+ GetCaster()->CastSpell(nullptr, SPELL_SUMMON_COPY_OF_MINIONS, true);
}
void Register() override
diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp
index abab9f7ead7..e0ac981b69c 100644
--- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp
@@ -246,7 +246,7 @@ class npc_corrupted_soul_fragment : public CreatureScript
if (instance->GetGuidData(DATA_BRONJAHM).GetCounter() != id)
return;
- me->CastSpell((Unit*)nullptr, SPELL_CONSUME_SOUL, true);
+ me->CastSpell(nullptr, SPELL_CONSUME_SOUL, true);
me->DespawnOrUnsummon();
}
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
index 7d620ae5a60..0545d3d19f6 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
@@ -2824,9 +2824,9 @@ class spell_hor_gunship_cannon_fire : public SpellScriptLoader
if (!urand(0, 2))
{
if (GetTarget()->GetEntry() == NPC_GUNSHIP_CANNON_HORDE)
- GetTarget()->CastSpell((Unit*)nullptr, SPELL_GUNSHIP_CANNON_FIRE_MISSILE_HORDE, true);
+ GetTarget()->CastSpell(nullptr, SPELL_GUNSHIP_CANNON_FIRE_MISSILE_HORDE, true);
else
- GetTarget()->CastSpell((Unit*)nullptr, SPELL_GUNSHIP_CANNON_FIRE_MISSILE_ALLIANCE, true);
+ GetTarget()->CastSpell(nullptr, SPELL_GUNSHIP_CANNON_FIRE_MISSILE_ALLIANCE, true);
}
}
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp
index 89f95a32cc8..ab439788c90 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp
@@ -346,7 +346,7 @@ class instance_halls_of_reflection : public InstanceMapScript
if (Creature* lichking = instance->GetCreature(TheLichKingEscapeGUID))
{
- lichking->CastSpell((Unit*)nullptr, SPELL_ACHIEV_CHECK, true);
+ lichking->CastSpell(nullptr, SPELL_ACHIEV_CHECK, true);
lichking->DespawnOrUnsummon(1);
}
break;
@@ -453,7 +453,7 @@ class instance_halls_of_reflection : public InstanceMapScript
if (_quelDelarState == NOT_STARTED)
{
if (Creature* bunny = instance->GetCreature(FrostmourneAltarBunnyGUID))
- bunny->CastSpell((Unit*)nullptr, SPELL_ESSENCE_OF_CAPTURED);
+ bunny->CastSpell(nullptr, SPELL_ESSENCE_OF_CAPTURED);
events.ScheduleEvent(EVENT_QUEL_DELAR_SUMMON_UTHER, 2000);
}
}
diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp
index f21d4fa007c..8b558d8e913 100644
--- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp
@@ -114,7 +114,9 @@ enum KrickPhase
enum Actions
{
- ACTION_OUTRO = 1
+ ACTION_OUTRO = 1,
+ ACTION_STORE_OLD_TARGET,
+ ACTION_RESET_THREAT
};
enum Points
@@ -144,13 +146,15 @@ class boss_ick : public CreatureScript
{
boss_ickAI(Creature* creature) : BossAI(creature, DATA_ICK)
{
- _tempThreat = 0;
+ _tempThreat = 0.0f;
}
void Reset() override
{
events.Reset();
instance->SetBossState(DATA_ICK, NOT_STARTED);
+ _oldTargetGUID.Clear();
+ _tempThreat = 0.0f;
}
Creature* GetKrick()
@@ -190,15 +194,29 @@ class boss_ick : public CreatureScript
instance->SetBossState(DATA_ICK, DONE);
}
- void SetTempThreat(float threat)
+ void DoAction(int32 actionId) override
{
- _tempThreat = threat;
- }
+ if (actionId == ACTION_STORE_OLD_TARGET)
+ {
+ if (Unit* victim = me->GetVictim())
+ {
+ _oldTargetGUID = victim->GetGUID();
+ _tempThreat = GetThreat(victim);
+ }
+ }
+ else if (actionId == ACTION_RESET_THREAT)
+ {
+ if (Unit* oldTarget = ObjectAccessor::GetUnit(*me, _oldTargetGUID))
+ {
+ if (Unit* current = me->GetVictim())
+ ModifyThreatByPercent(current, -100);
- void _ResetThreat(Unit* target)
- {
- ModifyThreatByPercent(target, -100);
- AddThreat(target, _tempThreat);
+ AddThreat(oldTarget, _tempThreat);
+ AttackStart(oldTarget);
+ _oldTargetGUID.Clear();
+ _tempThreat = 0.0f;
+ }
+ }
}
void UpdateAI(uint32 diff) override
@@ -262,7 +280,7 @@ class boss_ick : public CreatureScript
case EVENT_PURSUIT:
if (Creature* krick = GetKrick())
krick->AI()->Talk(SAY_KRICK_CHASE);
- DoCast(me, SPELL_PURSUIT);
+ me->CastCustomSpell(SPELL_PURSUIT, SPELLVALUE_MAX_TARGETS, 1, me);
break;
default:
break;
@@ -277,6 +295,7 @@ class boss_ick : public CreatureScript
private:
float _tempThreat;
+ ObjectGuid _oldTargetGUID;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -631,18 +650,15 @@ class spell_krick_pursuit : public SpellScriptLoader
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
{
- if (GetCaster())
- if (Creature* ick = GetCaster()->ToCreature())
- {
- if (Unit* target = ick->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 200.0f, true))
- {
- ick->AI()->Talk(SAY_ICK_CHASE_1, target);
- ick->AddAura(GetSpellInfo()->Id, target);
- ENSURE_AI(boss_ick::boss_ickAI, ick->AI())->SetTempThreat(ick->GetThreatManager().GetThreat(target));
- ick->GetThreatManager().AddThreat(target, float(GetEffectValue()), GetSpellInfo(), true, true);
- target->GetThreatManager().AddThreat(ick, float(GetEffectValue()), GetSpellInfo(), true, true);
- }
- }
+ Unit* target = GetHitUnit();
+ if (Creature* ick = GetCaster()->ToCreature())
+ {
+ ick->AI()->Talk(SAY_ICK_CHASE_1, target);
+ ick->AddAura(GetSpellInfo()->Id, target);
+ ick->AI()->DoAction(ACTION_STORE_OLD_TARGET);
+ ick->GetThreatManager().AddThreat(target, float(GetEffectValue()), GetSpellInfo(), true, true);
+ ick->AI()->AttackStart(target);
+ }
}
void Register() override
@@ -659,7 +675,7 @@ class spell_krick_pursuit : public SpellScriptLoader
{
if (Unit* caster = GetCaster())
if (Creature* creCaster = caster->ToCreature())
- ENSURE_AI(boss_ick::boss_ickAI, creCaster->AI())->_ResetThreat(GetTarget());
+ creCaster->AI()->DoAction(ACTION_RESET_THREAT);
}
void Register() override
diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp
index 4e62380b983..187ab353803 100644
--- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp
@@ -539,18 +539,18 @@ class spell_tyrannus_rimefang_icy_blast : public SpellScriptLoader
}
};
-class at_tyrannus_event_starter : public AreaTriggerScript
+class at_tyrannus_event_starter : public OnlyOnceAreaTriggerScript
{
public:
- at_tyrannus_event_starter() : AreaTriggerScript("at_tyrannus_event_starter") { }
+ at_tyrannus_event_starter() : OnlyOnceAreaTriggerScript("at_tyrannus_event_starter") { }
- bool OnTrigger(Player* player, AreaTriggerEntry const* /*at*/) override
+ bool _OnTrigger(Player* player, AreaTriggerEntry const* /*at*/) override
{
InstanceScript* instance = player->GetInstanceScript();
if (player->IsGameMaster() || !instance)
return false;
- if (instance->GetBossState(DATA_TYRANNUS) != IN_PROGRESS && instance->GetBossState(DATA_TYRANNUS) != DONE)
+ if (instance->GetBossState(DATA_TYRANNUS) != DONE)
if (Creature* tyrannus = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_TYRANNUS)))
{
tyrannus->AI()->DoAction(ACTION_START_INTRO);
diff --git a/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp b/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp
index c9e5848d2f5..4bd67f3e232 100644
--- a/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp
+++ b/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp
@@ -322,7 +322,7 @@ class instance_gundrak : public InstanceMapScript
if (GameObject* altar = GetGameObject(altarId))
if (Creature* trigger = altar->FindNearestCreature(NPC_ALTAR_TRIGGER, 10.0f))
- trigger->CastSpell((Unit*)nullptr, spellId, true);
+ trigger->CastSpell(nullptr, spellId, true);
// eventId equals statueId
ToggleGameObject(eventId, GO_STATE_READY);
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
index f038f653782..ffbc0901f31 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
@@ -222,7 +222,7 @@ class boss_blood_council_controller : public CreatureScript
struct boss_blood_council_controllerAI : public BossAI
{
- boss_blood_council_controllerAI(Creature* creature) : BossAI(creature, DATA_BLOOD_PRINCE_COUNCIL), _intro(true)
+ boss_blood_council_controllerAI(Creature* creature) : BossAI(creature, DATA_BLOOD_PRINCE_COUNCIL)
{
Initialize();
SetCombatMovement(false);
@@ -240,7 +240,7 @@ class boss_blood_council_controller : public CreatureScript
Initialize();
me->SummonCreatureGroup(SUMMON_PRINCES_GROUP);
- if (!_intro)
+ if (!instance->GetData(DATA_BLOOD_PRINCE_COUNCIL_INTRO))
for (uint32 bossData : PrincesData)
if (Creature* prince = ObjectAccessor::GetCreature(*me, instance->GetGuidData(bossData)))
{
@@ -311,7 +311,7 @@ class boss_blood_council_controller : public CreatureScript
uint32 GetData(uint32 data) const override
{
- if (data == DATA_INTRO && !_intro)
+ if (data == DATA_INTRO && !instance->GetData(DATA_BLOOD_PRINCE_COUNCIL_INTRO))
return DATA_INTRO_DONE;
return 0;
}
@@ -338,9 +338,9 @@ class boss_blood_council_controller : public CreatureScript
void DoAction(int32 actionId) override
{
- if (actionId == ACTION_START_INTRO && _intro && instance->GetBossState(DATA_BLOOD_PRINCE_COUNCIL) != DONE)
+ if (actionId == ACTION_START_INTRO && instance->GetData(DATA_BLOOD_PRINCE_COUNCIL_INTRO) && instance->GetBossState(DATA_BLOOD_PRINCE_COUNCIL) != DONE)
{
- _intro = false;
+ instance->SetData(DATA_BLOOD_PRINCE_COUNCIL_INTRO, 0);
if (Creature* bloodQueen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BLOOD_QUEEN_LANA_THEL_COUNCIL)))
bloodQueen->AI()->DoAction(ACTION_START_INTRO);
}
@@ -425,7 +425,6 @@ class boss_blood_council_controller : public CreatureScript
uint32 _invocationStage;
uint32 _resetCounter;
- bool _intro;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -445,7 +444,7 @@ struct BloodPrincesBossAI : public BossAI
{
_spawnHealth = 1;
if (!me->isDead())
- JustRespawned();
+ JustAppeared();
}
void Reset() override
@@ -493,7 +492,7 @@ struct BloodPrincesBossAI : public BossAI
}
}
- void JustRespawned() override
+ void JustAppeared() override
{
if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BLOOD_PRINCES_CONTROL)))
if (controller->AI()->GetData(DATA_INTRO) != DATA_INTRO_DONE)
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp
index 41b836922e1..e344a3181fc 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp
@@ -550,7 +550,7 @@ struct gunship_npc_AI : public ScriptedAI
Instance(creature->GetInstanceScript()), Slot(nullptr), Index(uint32(-1))
{
BurningPitchId = Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SPELL_BURNING_PITCH_A : SPELL_BURNING_PITCH_H;
- me->setRegeneratingHealth(false);
+ me->SetRegenerateHealth(false);
}
void SetData(uint32 type, uint32 data) override
@@ -676,7 +676,7 @@ class npc_gunship : public CreatureScript
_teamInInstance(creature->GetInstanceScript()->GetData(DATA_TEAM_IN_INSTANCE)),
_summonedFirstMage(false), _died(false)
{
- me->setRegeneratingHealth(false);
+ me->SetRegenerateHealth(false);
}
void DamageTaken(Unit* /*source*/, uint32& damage) override
@@ -857,7 +857,7 @@ class npc_high_overlord_saurfang_igb : public CreatureScript
{
_controller.ResetSlots(HORDE);
_controller.SetTransport(creature->GetTransport());
- me->setRegeneratingHealth(false);
+ me->SetRegenerateHealth(false);
me->m_CombatDistance = 70.0f;
_firstMageCooldown = time(nullptr) + 60;
_axethrowersYellCooldown = time_t(0);
@@ -1126,7 +1126,7 @@ class npc_muradin_bronzebeard_igb : public CreatureScript
{
_controller.ResetSlots(ALLIANCE);
_controller.SetTransport(creature->GetTransport());
- me->setRegeneratingHealth(false);
+ me->SetRegenerateHealth(false);
me->m_CombatDistance = 70.0f;
_firstMageCooldown = time(nullptr) + 60;
_riflemanYellCooldown = time_t(0);
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp
index 8a444b3d933..bf6920e741d 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp
@@ -203,7 +203,7 @@ class boss_lady_deathwhisper : public CreatureScript
struct boss_lady_deathwhisperAI : public BossAI
{
boss_lady_deathwhisperAI(Creature* creature) : BossAI(creature, DATA_LADY_DEATHWHISPER),
- _dominateMindCount(RAID_MODE<uint8>(0, 1, 1, 3)), _introDone(false)
+ _dominateMindCount(RAID_MODE<uint8>(0, 1, 1, 3))
{
Initialize();
}
@@ -237,43 +237,39 @@ class boss_lady_deathwhisper : public CreatureScript
if (action != ACTION_START_INTRO)
return;
- if (!_introDone)
+ Talk(SAY_INTRO_1);
+ _phase = PHASE_INTRO;
+ scheduler.Schedule(Seconds(10), GROUP_INTRO, [this](TaskContext context)
{
- _introDone = true;
- Talk(SAY_INTRO_1);
- _phase = PHASE_INTRO;
- scheduler.Schedule(Seconds(10), GROUP_INTRO, [this](TaskContext context)
+ switch (context.GetRepeatCounter())
{
- switch (context.GetRepeatCounter())
- {
- case 0:
- Talk(SAY_INTRO_2);
- context.Repeat(Seconds(21));
- break;
- case 1:
- Talk(SAY_INTRO_3);
- context.Repeat(Seconds(11));
- break;
- case 2:
- Talk(SAY_INTRO_4);
- context.Repeat(Seconds(9));
- break;
- case 3:
- Talk(SAY_INTRO_5);
- context.Repeat(Seconds(21));
- break;
- case 4:
- Talk(SAY_INTRO_6);
- context.Repeat(Seconds(10));
- break;
- case 5:
- Talk(SAY_INTRO_7);
- return;
- default:
- break;
- }
- });
- }
+ case 0:
+ Talk(SAY_INTRO_2);
+ context.Repeat(Seconds(21));
+ break;
+ case 1:
+ Talk(SAY_INTRO_3);
+ context.Repeat(Seconds(11));
+ break;
+ case 2:
+ Talk(SAY_INTRO_4);
+ context.Repeat(Seconds(9));
+ break;
+ case 3:
+ Talk(SAY_INTRO_5);
+ context.Repeat(Seconds(21));
+ break;
+ case 4:
+ Talk(SAY_INTRO_6);
+ context.Repeat(Seconds(10));
+ break;
+ case 5:
+ Talk(SAY_INTRO_7);
+ return;
+ default:
+ break;
+ }
+ });
}
void AttackStart(Unit* victim) override
@@ -585,7 +581,6 @@ class boss_lady_deathwhisper : public CreatureScript
uint32 _waveCounter;
uint8 const _dominateMindCount;
uint8 _phase;
- bool _introDone;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -1022,12 +1017,12 @@ class spell_deathwhisper_mana_barrier : public SpellScriptLoader
}
};
-class at_lady_deathwhisper_entrance : public AreaTriggerScript
+class at_lady_deathwhisper_entrance : public OnlyOnceAreaTriggerScript
{
public:
- at_lady_deathwhisper_entrance() : AreaTriggerScript("at_lady_deathwhisper_entrance") { }
+ at_lady_deathwhisper_entrance() : OnlyOnceAreaTriggerScript("at_lady_deathwhisper_entrance") { }
- bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
+ bool _OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
{
if (InstanceScript* instance = player->GetInstanceScript())
if (instance->GetBossState(DATA_LADY_DEATHWHISPER) != DONE)
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
index ca8a9356db6..7e7b372337e 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
@@ -140,7 +140,6 @@ class boss_lord_marrowgar : public CreatureScript
_boneStormDuration = RAID_MODE<uint32>(20000, 30000, 20000, 30000);
_baseSpeed = creature->GetSpeedRate(MOVE_RUN);
_coldflameLastPos.Relocate(creature);
- _introDone = false;
_boneSlice = false;
}
@@ -155,7 +154,6 @@ class boss_lord_marrowgar : public CreatureScript
events.ScheduleEvent(EVENT_COLDFLAME, 5000, EVENT_GROUP_SPECIAL);
events.ScheduleEvent(EVENT_WARN_BONE_STORM, urand(45000, 50000));
events.ScheduleEvent(EVENT_ENRAGE, 600000);
- _introDone = false;
_boneSlice = false;
_boneSpikeImmune.clear();
}
@@ -333,11 +331,7 @@ class boss_lord_marrowgar : public CreatureScript
_boneSpikeImmune.clear();
break;
case ACTION_TALK_ENTER_ZONE:
- if (!_introDone)
- {
Talk(SAY_ENTER_ZONE);
- _introDone = true;
- }
break;
default:
break;
@@ -350,7 +344,6 @@ class boss_lord_marrowgar : public CreatureScript
ObjectGuid _coldflameTarget;
uint32 _boneStormDuration;
float _baseSpeed;
- bool _introDone;
bool _boneSlice;
};
@@ -654,6 +647,15 @@ class spell_marrowgar_bone_spike_graveyard : public SpellScriptLoader
{
Unit* target = *itr;
target->CastSpell(target, BoneSpikeSummonId[i], true);
+ if (!target->IsAlive()) // make sure we don't get any stuck spikes on dead targets
+ {
+ if (Aura* aura = target->GetAura(SPELL_IMPALED))
+ {
+ if (Creature* spike = ObjectAccessor::GetCreature(*target, aura->GetCasterGUID()))
+ spike->DespawnOrUnsummon();
+ aura->Remove();
+ }
+ }
}
marrowgarAI->Talk(SAY_BONESPIKE);
@@ -752,12 +754,12 @@ class spell_marrowgar_bone_slice : public SpellScriptLoader
}
};
-class at_lord_marrowgar_entrance : public AreaTriggerScript
+class at_lord_marrowgar_entrance : public OnlyOnceAreaTriggerScript
{
public:
- at_lord_marrowgar_entrance() : AreaTriggerScript("at_lord_marrowgar_entrance") { }
+ at_lord_marrowgar_entrance() : OnlyOnceAreaTriggerScript("at_lord_marrowgar_entrance") { }
- bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
+ bool _OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
{
if (InstanceScript* instance = player->GetInstanceScript())
if (Creature* lordMarrowgar = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_LORD_MARROWGAR)))
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
index b23b3ca9917..e19b4187138 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
@@ -1118,7 +1118,7 @@ class spell_putricide_ooze_tank_protection : public SpellScriptLoader
PreventDefaultAction();
Unit* actionTarget = eventInfo.GetActionTarget();
- actionTarget->CastSpell((Unit*)nullptr, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, true, nullptr, aurEff);
+ actionTarget->CastSpell(nullptr, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
index 370578a3c47..c64e42762d2 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
@@ -194,7 +194,7 @@ class FrostBombExplosion : public BasicEvent
bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override
{
- _owner->CastSpell((Unit*)nullptr, SPELL_FROST_BOMB, false, nullptr, nullptr, _sindragosaGUID);
+ _owner->CastSpell(nullptr, SPELL_FROST_BOMB, false, nullptr, nullptr, _sindragosaGUID);
_owner->RemoveAurasDueToSpell(SPELL_FROST_BOMB_VISUAL);
return true;
}
@@ -226,7 +226,7 @@ class boss_sindragosa : public CreatureScript
struct boss_sindragosaAI : public BossAI
{
- boss_sindragosaAI(Creature* creature) : BossAI(creature, DATA_SINDRAGOSA), _summoned(false)
+ boss_sindragosaAI(Creature* creature) : BossAI(creature, DATA_SINDRAGOSA)
{
Initialize();
}
@@ -251,7 +251,7 @@ class boss_sindragosa : public CreatureScript
events.ScheduleEvent(EVENT_AIR_PHASE, 50000);
Initialize();
- if (!_summoned)
+ if (instance->GetData(DATA_SINDRAGOSA_INTRO))
{
me->SetCanFly(true);
me->SetDisableGravity(true);
@@ -311,10 +311,8 @@ class boss_sindragosa : public CreatureScript
{
if (action == ACTION_START_FROSTWYRM)
{
- if (_summoned)
- return;
- _summoned = true;
+ instance->SetData(DATA_SINDRAGOSA_INTRO, 0);
if (TempSummon* summon = me->ToTempSummon())
summon->SetTempSummonType(TEMPSUMMON_DEAD_DESPAWN);
@@ -565,7 +563,6 @@ class boss_sindragosa : public CreatureScript
uint8 _mysticBuffetStack;
bool _isInAirPhase;
bool _isThirdPhase;
- bool _summoned;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -688,9 +685,9 @@ class npc_spinestalker : public CreatureScript
}
}
- void JustRespawned() override
+ void JustAppeared() override
{
- ScriptedAI::JustRespawned();
+ ScriptedAI::JustAppeared();
_instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, me->GetSpawnId()); // this cannot be in Reset because reset also happens on evade
}
@@ -825,9 +822,9 @@ class npc_rimefang : public CreatureScript
}
}
- void JustRespawned() override
+ void JustAppeared() override
{
- ScriptedAI::JustRespawned();
+ ScriptedAI::JustAppeared();
_instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, me->GetSpawnId()); // this cannot be in Reset because reset also happens on evade
}
@@ -991,9 +988,9 @@ class npc_sindragosa_trash : public CreatureScript
Initialize();
}
- void JustRespawned() override
+ void JustAppeared() override
{
- ScriptedAI::JustRespawned();
+ ScriptedAI::JustAppeared();
// Increase add count
if (me->GetEntry() == NPC_FROSTWING_WHELP)
@@ -1616,12 +1613,12 @@ public:
}
};
-class at_sindragosa_lair : public AreaTriggerScript
+class at_sindragosa_lair : public OnlyOnceAreaTriggerScript
{
public:
- at_sindragosa_lair() : AreaTriggerScript("at_sindragosa_lair") { }
+ at_sindragosa_lair() : OnlyOnceAreaTriggerScript("at_sindragosa_lair") { }
- bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
+ bool _OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
{
if (InstanceScript* instance = player->GetInstanceScript())
{
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
index d00e56606b5..7b1de4c8bfe 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
@@ -268,7 +268,10 @@ enum Events
// Strangulate Vehicle (Harvest Soul)
EVENT_TELEPORT,
EVENT_MOVE_TO_LICH_KING,
- EVENT_DESPAWN_SELF
+ EVENT_DESPAWN_SELF,
+
+ //Spirit Bomb
+ EVENT_BOMB_EXPLOSION
};
enum EventGroups
@@ -472,7 +475,7 @@ class VileSpiritActivateEvent : public BasicEvent
{
_owner->SetReactState(REACT_AGGRESSIVE);
_owner->CastSpell(_owner, SPELL_VILE_SPIRIT_MOVE_SEARCH, true);
- _owner->CastSpell((Unit*)nullptr, SPELL_VILE_SPIRIT_DAMAGE_SEARCH, true);
+ _owner->CastSpell(nullptr, SPELL_VILE_SPIRIT_DAMAGE_SEARCH, true);
return true;
}
@@ -626,8 +629,8 @@ class boss_the_lich_king : public CreatureScript
me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, 0, 5000);
break;
case ACTION_BREAK_FROSTMOURNE:
- me->CastSpell((Unit*)nullptr, SPELL_SUMMON_BROKEN_FROSTMOURNE, TRIGGERED_IGNORE_CAST_IN_PROGRESS);
- me->CastSpell((Unit*)nullptr, SPELL_SUMMON_BROKEN_FROSTMOURNE_2, TRIGGERED_IGNORE_CAST_IN_PROGRESS);
+ me->CastSpell(nullptr, SPELL_SUMMON_BROKEN_FROSTMOURNE, TRIGGERED_IGNORE_CAST_IN_PROGRESS);
+ me->CastSpell(nullptr, SPELL_SUMMON_BROKEN_FROSTMOURNE_2, TRIGGERED_IGNORE_CAST_IN_PROGRESS);
SetEquipmentSlots(false, EQUIP_BROKEN_FROSTMOURNE);
events.ScheduleEvent(EVENT_OUTRO_TALK_6, 2500, 0, PHASE_OUTRO);
break;
@@ -709,7 +712,7 @@ class boss_the_lich_king : public CreatureScript
summons.DespawnAll();
me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_FURY_OF_FROSTMOURNE);
me->InterruptNonMeleeSpells(true);
- me->CastSpell((Unit*)nullptr, SPELL_FURY_OF_FROSTMOURNE, TRIGGERED_NONE);
+ me->CastSpell(nullptr, SPELL_FURY_OF_FROSTMOURNE, TRIGGERED_NONE);
me->SetWalk(true);
events.ScheduleEvent(EVENT_OUTRO_TALK_1, 2600, 0, PHASE_OUTRO);
events.ScheduleEvent(EVENT_OUTRO_EMOTE_TALK, 6600, 0, PHASE_OUTRO);
@@ -756,7 +759,7 @@ class boss_the_lich_king : public CreatureScript
break;
case NPC_FROSTMOURNE_TRIGGER:
{
- summon->CastSpell((Unit*)nullptr, SPELL_BROKEN_FROSTMOURNE, true);
+ summon->CastSpell(nullptr, SPELL_BROKEN_FROSTMOURNE, true);
me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, LIGHT_SOULSTORM, 10000);
me->GetMap()->SetZoneWeather(AREA_ICECROWN_CITADEL, WEATHER_STATE_BLACKSNOW, 0.5f);
@@ -815,6 +818,7 @@ class boss_the_lich_king : public CreatureScript
{
me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, LIGHT_SNOWSTORM, 5000);
me->GetMap()->SetZoneWeather(AREA_ICECROWN_CITADEL, WEATHER_STATE_LIGHT_SNOW, 0.5f);
+ summons.DespawnEntry(NPC_SHADOW_TRAP);
}
}
@@ -842,8 +846,6 @@ class boss_the_lich_king : public CreatureScript
Talk(SAY_LK_REMORSELESS_WINTER);
me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL);
DoCast(me, SPELL_REMORSELESS_WINTER_1);
- summons.DespawnEntry(NPC_SHADOW_TRAP);
- events.DelayEvents(62500, EVENT_GROUP_BERSERK); // delay berserk timer, its not ticking during phase transitions
events.ScheduleEvent(EVENT_QUAKE, 62500, 0, PHASE_TRANSITION);
events.ScheduleEvent(EVENT_PAIN_AND_SUFFERING, 4000, 0, PHASE_TRANSITION);
events.ScheduleEvent(EVENT_SUMMON_ICE_SPHERE, 8000, 0, PHASE_TRANSITION);
@@ -859,7 +861,6 @@ class boss_the_lich_king : public CreatureScript
me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL);
DoCast(me, SPELL_REMORSELESS_WINTER_2);
summons.DespawnEntry(NPC_VALKYR_SHADOWGUARD);
- events.DelayEvents(62500, EVENT_GROUP_BERSERK); // delay berserk timer, its not ticking during phase transitions
events.ScheduleEvent(EVENT_QUAKE_2, 62500, 0, PHASE_TRANSITION);
events.ScheduleEvent(EVENT_PAIN_AND_SUFFERING, 6000, 0, PHASE_TRANSITION);
events.ScheduleEvent(EVENT_SUMMON_ICE_SPHERE, 8000, 0, PHASE_TRANSITION);
@@ -963,7 +964,7 @@ class boss_the_lich_king : public CreatureScript
events.ScheduleEvent(EVENT_NECROTIC_PLAGUE, urand(30000, 33000), 0, PHASE_ONE);
break;
case EVENT_SHADOW_TRAP:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(me)))
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, SpellTargetSelector(me, SPELL_SHADOW_TRAP)))
DoCast(target, SPELL_SHADOW_TRAP);
events.ScheduleEvent(EVENT_SHADOW_TRAP, 15500, 0, PHASE_ONE);
break;
@@ -972,7 +973,7 @@ class boss_the_lich_king : public CreatureScript
events.ScheduleEvent(EVENT_SOUL_REAPER, urand(33000, 35000), 0, PHASE_TWO_THREE);
break;
case EVENT_DEFILE:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, true, -SPELL_HARVEST_SOUL_VALKYR))
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, true, -SPELL_HARVEST_SOUL_VALKYR))
{
Talk(EMOTE_DEFILE_WARNING);
DoCast(target, SPELL_DEFILE);
@@ -1059,7 +1060,6 @@ class boss_the_lich_king : public CreatureScript
summon->RemoveAurasDueToSpell(SPELL_VILE_SPIRIT_MOVE_SEARCH);
summon->RemoveAurasDueToSpell(SPELL_VILE_SPIRIT_DAMAGE_SEARCH);
summon->GetMotionMaster()->MoveTargetedHome();
- summon->GetMotionMaster()->MoveRandom(10.0f);
}
else if (summon->GetEntry() == NPC_RAGING_SPIRIT)
summon->AI()->DoAction(ACTION_DISABLE_RAGING);
@@ -1076,6 +1076,7 @@ class boss_the_lich_king : public CreatureScript
{
triggers.sort(Trinity::ObjectDistanceOrderPred(terenas, true));
Creature* spawner = triggers.front();
+ spawner->setActive(true);
spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_1, true); // summons bombs randomly
spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_2, true); // summons bombs on players
spawner->m_Events.AddEvent(new TriggerWickedSpirit(spawner), spawner->m_Events.CalculateTime(3000));
@@ -1119,11 +1120,11 @@ class boss_the_lich_king : public CreatureScript
Talk(SAY_LK_OUTRO_6);
if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING)))
tirion->SetFacingToObject(me);
- me->CastSpell((Unit*)nullptr, SPELL_SUMMON_BROKEN_FROSTMOURNE_3, TRIGGERED_IGNORE_CAST_IN_PROGRESS);
+ me->CastSpell(nullptr, SPELL_SUMMON_BROKEN_FROSTMOURNE_3, TRIGGERED_IGNORE_CAST_IN_PROGRESS);
SetEquipmentSlots(false, EQUIP_UNEQUIP);
break;
case EVENT_OUTRO_SOUL_BARRAGE:
- me->CastSpell((Unit*)nullptr, SPELL_SOUL_BARRAGE, TRIGGERED_IGNORE_CAST_IN_PROGRESS);
+ me->CastSpell(nullptr, SPELL_SOUL_BARRAGE, TRIGGERED_IGNORE_CAST_IN_PROGRESS);
sCreatureTextMgr->SendSound(me, SOUND_PAIN, CHAT_MSG_MONSTER_YELL, 0, TEXT_RANGE_NORMAL, TEAM_OTHER, false);
// set flight
me->SetDisableGravity(true);
@@ -1693,7 +1694,7 @@ class npc_strangulate_vehicle : public CreatureScript
{
if (Unit* summoner = summ->GetSummoner())
{
- summoner->CastSpell((Unit*)nullptr, SPELL_HARVEST_SOUL_VISUAL, true);
+ summoner->CastSpell(nullptr, SPELL_HARVEST_SOUL_VISUAL, true);
summoner->ExitVehicle(summoner);
if (!IsHeroic())
summoner->CastSpell(summoner, SPELL_HARVEST_SOUL_TELEPORT, true);
@@ -1775,7 +1776,7 @@ class npc_terenas_menethil : public CreatureScript
}
break;
case ACTION_TELEPORT_BACK:
- me->CastSpell((Unit*)nullptr, SPELL_RESTORE_SOUL, TRIGGERED_NONE);
+ me->CastSpell(nullptr, SPELL_RESTORE_SOUL, TRIGGERED_NONE);
me->DespawnOrUnsummon(3000);
break;
default:
@@ -1805,7 +1806,7 @@ class npc_terenas_menethil : public CreatureScript
_events.ScheduleEvent(EVENT_TELEPORT_BACK, 1000);
if (Creature* warden = me->FindNearestCreature(NPC_SPIRIT_WARDEN, 20.0f))
{
- warden->CastSpell((Unit*)nullptr, SPELL_DESTROY_SOUL, TRIGGERED_NONE);
+ warden->CastSpell(nullptr, SPELL_DESTROY_SOUL, TRIGGERED_NONE);
warden->DespawnOrUnsummon(2000);
}
@@ -1863,7 +1864,7 @@ class npc_terenas_menethil : public CreatureScript
case EVENT_DESTROY_SOUL:
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
if (Creature* warden = me->FindNearestCreature(NPC_SPIRIT_WARDEN, 20.0f))
- warden->CastSpell((Unit*)nullptr, SPELL_DESTROY_SOUL, TRIGGERED_NONE);
+ warden->CastSpell(nullptr, SPELL_DESTROY_SOUL, TRIGGERED_NONE);
DoCast(SPELL_TERENAS_LOSES_INSIDE);
_events.ScheduleEvent(EVENT_TELEPORT_BACK, 1000);
break;
@@ -1976,20 +1977,29 @@ class npc_spirit_bomb : public CreatureScript
if (type != POINT_MOTION_TYPE || point != POINT_GROUND)
return;
- me->RemoveAllAuras();
- DoCastAOE(SPELL_EXPLOSION);
- me->DespawnOrUnsummon(1000);
+ _events.ScheduleEvent(EVENT_BOMB_EXPLOSION, 3000);
}
void AttackStart(Unit* /*victim*/) override
{
}
- void UpdateAI(uint32 /*diff*/) override
+ void UpdateAI(uint32 diff) override
{
UpdateVictim();
- // no melee attacks
+
+ _events.Update(diff);
+
+ if (_events.ExecuteEvent() == EVENT_BOMB_EXPLOSION)
+ {
+ me->RemoveAllAuras();
+ DoCastAOE(SPELL_EXPLOSION);
+ me->DespawnOrUnsummon(1000);
+ }
}
+
+ private:
+ EventMap _events;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -2318,7 +2328,7 @@ class spell_the_lich_king_shadow_trap_periodic : public SpellScriptLoader
if (targets.empty())
return;
- GetCaster()->CastSpell((Unit*)nullptr, SPELL_SHADOW_TRAP_KNOCKBACK, true);
+ GetCaster()->CastSpell(nullptr, SPELL_SHADOW_TRAP_KNOCKBACK, true);
}
void Register() override
@@ -2511,8 +2521,9 @@ class spell_the_lich_king_summon_into_air : public SpellScriptLoader
// spirit bombs get higher
if (GetSpellInfo()->Effects[effIndex].MiscValue == NPC_SPIRIT_BOMB)
{
- dest->RelocateOffset(offset);
- GetHitDest()->RelocateOffset(offset);
+ static Position const offsetExtra = { 0.0f, 0.0f, 5.0f, 0.0f };
+ dest->RelocateOffset(offsetExtra);
+ GetHitDest()->RelocateOffset(offsetExtra);
}
}
@@ -2700,7 +2711,7 @@ class spell_the_lich_king_vile_spirits : public SpellScriptLoader
void OnPeriodic(AuraEffect const* aurEff)
{
if (_is25Man || ((aurEff->GetTickNumber() - 1) % 5))
- GetTarget()->CastSpell((Unit*)nullptr, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, true, nullptr, aurEff, GetCasterGUID());
+ GetTarget()->CastSpell(nullptr, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, true, nullptr, aurEff, GetCasterGUID());
}
void Register() override
@@ -2823,7 +2834,7 @@ class spell_the_lich_king_vile_spirit_damage_target_search : public SpellScriptL
if (TempSummon* summon = GetCaster()->ToTempSummon())
if (Unit* summoner = summon->GetSummoner())
summoner->GetAI()->SetData(DATA_VILE, 1);
- GetCaster()->CastSpell((Unit*)nullptr, SPELL_SPIRIT_BURST, true);
+ GetCaster()->CastSpell(nullptr, SPELL_SPIRIT_BURST, true);
GetCaster()->ToCreature()->DespawnOrUnsummon(3000);
GetCaster()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
@@ -2858,7 +2869,7 @@ class spell_the_lich_king_harvest_soul : public SpellScriptLoader
{
// m_originalCaster to allow stacking from different casters, meh
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH)
- GetTarget()->CastSpell((Unit*)nullptr, SPELL_HARVESTED_SOUL, true, nullptr, nullptr, GetTarget()->GetInstanceScript()->GetGuidData(DATA_THE_LICH_KING));
+ GetTarget()->CastSpell(nullptr, SPELL_HARVESTED_SOUL, true, nullptr, nullptr, GetTarget()->GetInstanceScript()->GetGuidData(DATA_THE_LICH_KING));
}
void Register() override
@@ -3054,7 +3065,7 @@ class spell_the_lich_king_in_frostmourne_room : public SpellScriptLoader
{
// m_originalCaster to allow stacking from different casters, meh
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH)
- GetTarget()->CastSpell((Unit*)nullptr, SPELL_HARVESTED_SOUL, true, nullptr, nullptr, GetTarget()->GetInstanceScript()->GetGuidData(DATA_THE_LICH_KING));
+ GetTarget()->CastSpell(nullptr, SPELL_HARVESTED_SOUL, true, nullptr, nullptr, GetTarget()->GetInstanceScript()->GetGuidData(DATA_THE_LICH_KING));
}
void Register() override
@@ -3081,7 +3092,7 @@ class spell_the_lich_king_summon_spirit_bomb : public SpellScriptLoader
void HandleScript(SpellEffIndex effIndex)
{
PreventHitDefaultEffect(effIndex);
- GetHitUnit()->CastSpell((Unit*)nullptr, uint32(GetEffectValue()), true);
+ GetHitUnit()->CastSpell(nullptr, uint32(GetEffectValue()), true);
}
void Register() override
@@ -3139,7 +3150,7 @@ class spell_the_lich_king_jump : public SpellScriptLoader
{
PreventHitDefaultEffect(effIndex);
GetHitUnit()->RemoveAurasDueToSpell(SPELL_RAISE_DEAD);
- GetHitUnit()->CastSpell((Unit*)nullptr, SPELL_JUMP_2, true);
+ GetHitUnit()->CastSpell(nullptr, SPELL_JUMP_2, true);
if (Creature* creature = GetHitCreature())
creature->AI()->DoAction(ACTION_BREAK_FROSTMOURNE);
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp
index 493b759e0f7..d2cc08dcc6e 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp
@@ -264,7 +264,7 @@ class ValithriaDespawner : public BasicEvent
creature->SetRespawnDelay(10);
if (CreatureData const* data = creature->GetCreatureData())
- creature->UpdatePosition(data->posX, data->posY, data->posZ, data->orientation);
+ creature->UpdatePosition(data->spawnPoint);
creature->DespawnOrUnsummon();
creature->SetCorpseDelay(corpseDelay);
@@ -1467,7 +1467,7 @@ class spell_dreamwalker_twisted_nightmares : public SpellScriptLoader
// return;
if (InstanceScript* instance = GetHitUnit()->GetInstanceScript())
- GetHitUnit()->CastSpell((Unit*)nullptr, GetSpellInfo()->Effects[effIndex].TriggerSpell, true, nullptr, nullptr, instance->GetGuidData(DATA_VALITHRIA_DREAMWALKER));
+ GetHitUnit()->CastSpell(nullptr, GetSpellInfo()->Effects[effIndex].TriggerSpell, true, nullptr, nullptr, instance->GetGuidData(DATA_VALITHRIA_DREAMWALKER));
}
void Register() override
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp
index ed85ee3fa17..59a95ae0b9c 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp
@@ -354,7 +354,7 @@ class FrostwingGauntletRespawner
creature->SetRespawnDelay(2);
if (CreatureData const* data = creature->GetCreatureData())
- creature->UpdatePosition(data->posX, data->posY, data->posZ, data->orientation);
+ creature->UpdatePosition(data->spawnPoint);
creature->DespawnOrUnsummon();
creature->SetCorpseDelay(corpseDelay);
@@ -955,9 +955,9 @@ class npc_crok_scourgebane : public CreatureScript
public:
npc_crok_scourgebane() : CreatureScript("npc_crok_scourgebane") { }
- struct npc_crok_scourgebaneAI : public npc_escortAI
+ struct npc_crok_scourgebaneAI : public EscortAI
{
- npc_crok_scourgebaneAI(Creature* creature) : npc_escortAI(creature),
+ npc_crok_scourgebaneAI(Creature* creature) : EscortAI(creature),
_instance(creature->GetInstanceScript()), _respawnTime(creature->GetRespawnDelay()),
_corpseDelay(creature->GetCorpseDelay())
{
@@ -1036,7 +1036,7 @@ class npc_crok_scourgebane : public CreatureScript
}
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -1067,7 +1067,7 @@ class npc_crok_scourgebane : public CreatureScript
}
}
- void WaypointStart(uint32 waypointId) override
+ void WaypointStarted(uint32 waypointId, uint32 /*pathId*/) override
{
_currentWPid = waypointId;
switch (waypointId)
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
index e40ba687312..a9ea390e834 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
+++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
@@ -120,7 +120,9 @@ enum ICDataTypes
DATA_TERENAS_MENETHIL = 39,
DATA_ENEMY_GUNSHIP = 40,
DATA_UPPERSPIRE_TELE_ACT = 41, /// also used by conditions
- DATA_BLOOD_QUEEN_LANA_THEL_COUNCIL = 42
+ DATA_BLOOD_QUEEN_LANA_THEL_COUNCIL = 42,
+ DATA_BLOOD_PRINCE_COUNCIL_INTRO = 43,
+ DATA_SINDRAGOSA_INTRO = 44
};
enum ICCreaturesIds
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
index ffc899b4d0d..c986bb25c6b 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
@@ -147,6 +147,8 @@ class instance_icecrown_citadel : public InstanceMapScript
UpperSpireTeleporterActiveState = NOT_STARTED;
BloodQuickeningState = NOT_STARTED;
BloodQuickeningMinutes = 0;
+ BloodPrinceIntro = 1;
+ SindragosaIntro = 1;
}
// A function to help reduce the number of lines for teleporter management.
@@ -392,13 +394,13 @@ class instance_icecrown_citadel : public InstanceMapScript
break;
case NPC_ZAFOD_BOOMBOX:
if (GameObjectTemplate const* go = sObjectMgr->GetGameObjectTemplate(GO_THE_SKYBREAKER_A))
- if ((TeamInInstance == ALLIANCE && data->mapid == go->moTransport.mapID) ||
- (TeamInInstance == HORDE && data->mapid != go->moTransport.mapID))
+ if ((TeamInInstance == ALLIANCE && data->spawnPoint.GetMapId() == go->moTransport.mapID) ||
+ (TeamInInstance == HORDE && data->spawnPoint.GetMapId() != go->moTransport.mapID))
return entry;
return 0;
case NPC_IGB_MURADIN_BRONZEBEARD:
- if ((TeamInInstance == ALLIANCE && data->posX > 10.0f) ||
- (TeamInInstance == HORDE && data->posX < 10.0f))
+ if ((TeamInInstance == ALLIANCE && data->spawnPoint.GetPositionX() > 10.0f) ||
+ (TeamInInstance == HORDE && data->spawnPoint.GetPositionX() < 10.0f))
return entry;
return 0;
default:
@@ -739,6 +741,10 @@ class instance_icecrown_citadel : public InstanceMapScript
return BloodQuickeningState;
case DATA_HEROIC_ATTEMPTS:
return HeroicAttempts;
+ case DATA_BLOOD_PRINCE_COUNCIL_INTRO:
+ return BloodPrinceIntro;
+ case DATA_SINDRAGOSA_INTRO:
+ return SindragosaIntro;
default:
break;
}
@@ -1116,6 +1122,12 @@ class instance_icecrown_citadel : public InstanceMapScript
SaveToDB();
}
break;
+ case DATA_BLOOD_PRINCE_COUNCIL_INTRO:
+ BloodPrinceIntro = data;
+ break;
+ case DATA_SINDRAGOSA_INTRO:
+ SindragosaIntro = data;
+ break;
default:
break;
}
@@ -1308,7 +1320,7 @@ class instance_icecrown_citadel : public InstanceMapScript
return;
stalkers.sort(Trinity::ObjectDistanceOrderPred(teleporter));
- stalkers.front()->CastSpell((Unit*)nullptr, SPELL_ARTHAS_TELEPORTER_CEREMONY, false);
+ stalkers.front()->CastSpell(nullptr, SPELL_ARTHAS_TELEPORTER_CEREMONY, false);
stalkers.pop_front();
for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr)
(*itr)->AI()->Reset();
@@ -1530,6 +1542,8 @@ class instance_icecrown_citadel : public InstanceMapScript
uint32 BloodQuickeningState;
uint32 HeroicAttempts;
uint16 BloodQuickeningMinutes;
+ uint8 BloodPrinceIntro;
+ uint8 SindragosaIntro;
bool IsBonedEligible;
bool IsOozeDanceEligible;
bool IsNauseaEligible;
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp
index 5454ff7c848..8a481bff9ce 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp
@@ -96,7 +96,7 @@ public:
void InitializeAI() override
{
- if (!me->isDead())
+ if (!me->isDead() && instance->GetBossState(BOSS_ANUBREKHAN) != DONE)
{
Reset();
SummonGuards();
@@ -239,20 +239,19 @@ public:
};
-class at_anubrekhan_entrance : public AreaTriggerScript
+class at_anubrekhan_entrance : public OnlyOnceAreaTriggerScript
{
public:
- at_anubrekhan_entrance() : AreaTriggerScript("at_anubrekhan_entrance") { }
+ at_anubrekhan_entrance() : OnlyOnceAreaTriggerScript("at_anubrekhan_entrance") { }
- bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
+ bool _OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
{
InstanceScript* instance = player->GetInstanceScript();
- if (!instance || instance->GetData(DATA_HAD_ANUBREKHAN_GREET) || instance->GetBossState(BOSS_ANUBREKHAN) != NOT_STARTED)
+ if (!instance || instance->GetBossState(BOSS_ANUBREKHAN) != NOT_STARTED)
return true;
if (Creature* anub = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_ANUBREKHAN)))
anub->AI()->Talk(SAY_GREET);
- instance->SetData(DATA_HAD_ANUBREKHAN_GREET, 1u);
return true;
}
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp
index da3d95a5173..9b7df0d4f40 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp
@@ -83,7 +83,7 @@ class boss_faerlina : public CreatureScript
void InitializeAI() override
{
- if (!me->isDead())
+ if (!me->isDead() && instance->GetBossState(BOSS_FAERLINA) != DONE)
{
Reset();
SummonAdds();
@@ -260,20 +260,19 @@ class achievement_momma_said_knock_you_out : public AchievementCriteriaScript
}
};
-class at_faerlina_entrance : public AreaTriggerScript
+class at_faerlina_entrance : public OnlyOnceAreaTriggerScript
{
public:
- at_faerlina_entrance() : AreaTriggerScript("at_faerlina_entrance") { }
+ at_faerlina_entrance() : OnlyOnceAreaTriggerScript("at_faerlina_entrance") { }
- bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
+ bool _OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
{
InstanceScript* instance = player->GetInstanceScript();
- if (!instance || instance->GetData(DATA_HAD_FAERLINA_GREET) || instance->GetBossState(BOSS_FAERLINA) != NOT_STARTED)
+ if (!instance || instance->GetBossState(BOSS_FAERLINA) != NOT_STARTED)
return true;
if (Creature* faerlina = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_FAERLINA)))
faerlina->AI()->Talk(SAY_GREET);
- instance->SetData(DATA_HAD_FAERLINA_GREET, 1u);
return true;
}
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp
index 0fb00d18fd3..51deb5b4375 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp
@@ -265,14 +265,9 @@ struct boss_four_horsemen_baseAI : public BossAI
for (Horseman boss : horsemen)
{
if (Creature* cBoss = getHorsemanHandle(boss))
- {
- cBoss->DespawnOrUnsummon();
- cBoss->SetRespawnTime(15);
- }
+ cBoss->DespawnOrUnsummon(0, Seconds(15));
else
- {
TC_LOG_WARN("scripts", "FourHorsemenAI: Encounter resetting but horseman with id %u is not present", uint32(boss));
- }
}
}
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp
index add15715165..75e1a5b2386 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp
@@ -123,7 +123,7 @@ public:
events.ScheduleEvent(EVENT_DISRUPT, randtime(Seconds(15), Seconds(20)), 0, PHASE_FIGHT);
events.ScheduleEvent(EVENT_FEVER, randtime(Seconds(10), Seconds(20)), 0, PHASE_FIGHT);
events.ScheduleEvent(EVENT_DANCE, Minutes(1) + Seconds(30), 0, PHASE_FIGHT);
- events.ScheduleEvent(EVENT_ERUPT, Seconds(15), 0, PHASE_FIGHT);
+ events.ScheduleEvent(EVENT_ERUPT, Seconds(15));
_safetyDance = true;
@@ -172,7 +172,7 @@ public:
DoCast(SPELL_TELEPORT_SELF);
DoCastAOE(SPELL_PLAGUE_CLOUD);
events.ScheduleEvent(EVENT_DANCE_END, Seconds(45), 0, PHASE_DANCE);
- events.ScheduleEvent(EVENT_ERUPT, Seconds(10));
+ events.RescheduleEvent(EVENT_ERUPT, Seconds(10));
break;
case EVENT_DANCE_END:
events.SetPhase(PHASE_FIGHT);
@@ -181,7 +181,7 @@ public:
events.ScheduleEvent(EVENT_DISRUPT, randtime(Seconds(10), Seconds(25)), 0, PHASE_FIGHT);
events.ScheduleEvent(EVENT_FEVER, randtime(Seconds(15), Seconds(20)), 0, PHASE_FIGHT);
events.ScheduleEvent(EVENT_DANCE, Minutes(1) + Seconds(30), 0, PHASE_FIGHT);
- events.ScheduleEvent(EVENT_ERUPT, Seconds(15), 0, PHASE_FIGHT);
+ events.RescheduleEvent(EVENT_ERUPT, Seconds(15));
me->CastStop();
me->SetReactState(REACT_AGGRESSIVE);
DoZoneInCombat();
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp b/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp
index 46ab982c8a9..adce3c76070 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp
@@ -127,29 +127,29 @@ public:
auto list = mgr.GetModifiableThreatList();
auto it = list.begin(), end = list.end();
if (it == end)
+ {
EnterEvadeMode(EVADE_REASON_NO_HOSTILES);
+ return;
+ }
if ((*it)->GetVictim() != currentVictim)
secondThreat = *it;
- if ((!secondThreat || Is25ManRaid()) && (++it != end))
+ if ((!secondThreat || Is25ManRaid()) && (++it != end && (*it)->IsAvailable()))
{
if ((*it)->GetVictim() != currentVictim)
(secondThreat ? thirdThreat : secondThreat) = *it;
- if (!thirdThreat && Is25ManRaid() && (++it != end))
+ if (!thirdThreat && Is25ManRaid() && (++it != end && (*it)->IsAvailable()))
thirdThreat = *it;
}
Unit* pHatefulTarget = nullptr;
- if (!thirdThreat)
+ if (!secondThreat)
+ pHatefulTarget = currentVictim;
+ else if (!thirdThreat)
pHatefulTarget = secondThreat->GetVictim();
- else if (secondThreat)
+ else
pHatefulTarget = (secondThreat->GetVictim()->GetHealth() < thirdThreat->GetVictim()->GetHealth()) ? thirdThreat->GetVictim() : secondThreat->GetVictim();
- if (!pHatefulTarget)
- pHatefulTarget = me->GetVictim();
-
- DoCast(pHatefulTarget, SPELL_HATEFUL_STRIKE, true);
-
// add threat to highest threat targets
AddThreat(currentVictim, HATEFUL_THREAT_AMT);
if (secondThreat)
@@ -157,6 +157,8 @@ public:
if (thirdThreat)
thirdThreat->AddThreat(HATEFUL_THREAT_AMT);
+ DoCast(pHatefulTarget, SPELL_HATEFUL_STRIKE, true);
+
events.Repeat(Seconds(1));
break;
}
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp b/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp
index 58da5a92295..ac27c44d1de 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp
@@ -79,7 +79,7 @@ public:
void InitializeAI() override
{
- if (!me->isDead())
+ if (!me->isDead() && instance->GetBossState(BOSS_RAZUVIOUS) != DONE)
{
Reset();
SummonAdds();
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp
index 9f82e3ce4b3..1f279323591 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp
@@ -31,15 +31,12 @@ enum Phases
PHASE_NOT_ENGAGED = 1,
PHASE_PETS,
PHASE_TRANSITION,
- PHASE_THADDIUS,
- PHASE_RESETTING
+ PHASE_THADDIUS
};
enum AIActions
{
- ACTION_RESET_ENCOUNTER_TIMER = -1, // sent from instance AI
ACTION_BEGIN_RESET_ENCOUNTER = 0, // sent from thaddius to pets to trigger despawn and encounter reset
- ACTION_RESET_ENCOUNTER, // sent from thaddius to pets to trigger respawn and full reset
ACTION_FEUGEN_DIED, // sent from respective pet to thaddius to indicate death
ACTION_STALAGG_DIED, // ^
ACTION_FEUGEN_RESET, // pet to thaddius
@@ -160,321 +157,291 @@ enum ThaddiusSpells
SPELL_NEGATIVE_CHARGE_AMP = 29660,
};
-class boss_thaddius : public CreatureScript
+struct boss_thaddius : public BossAI
{
-public:
- boss_thaddius() : CreatureScript("boss_thaddius") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetNaxxramasAI<boss_thaddiusAI>(creature);
- }
-
- struct boss_thaddiusAI : public BossAI
- {
- public:
- boss_thaddiusAI(Creature* creature) : BossAI(creature, BOSS_THADDIUS), stalaggAlive(true), feugenAlive(true), ballLightningUnlocked(false), ballLightningEnabled(false), shockingEligibility(true) {}
+ public:
+ boss_thaddius(Creature* creature) : BossAI(creature, BOSS_THADDIUS), stalaggAlive(true), feugenAlive(true), ballLightningUnlocked(false), ballLightningEnabled(false), shockingEligibility(true) {}
- void InitializeAI() override
+ void InitializeAI() override
+ {
+ if (instance->GetBossState(BOSS_THADDIUS) != DONE)
{
- if (instance->GetBossState(BOSS_THADDIUS) != DONE)
- {
- events.SetPhase(PHASE_NOT_ENGAGED);
- SetCombatMovement(false);
-
- // initialize everything properly, and ensure that the coils are loaded by the time we initialize
- BeginResetEncounter(true);
- }
+ events.SetPhase(PHASE_NOT_ENGAGED);
+ SetCombatMovement(false);
}
+ }
- void KilledUnit(Unit* victim) override
- {
- if (victim->GetTypeId() == TYPEID_PLAYER)
- Talk(SAY_SLAY);
- }
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SLAY);
+ }
- void Reset() override { }
+ void Reset() override { }
- void EnterEvadeMode(EvadeReason why) override
+ void EnterEvadeMode(EvadeReason why) override
+ {
+ if (!ballLightningEnabled && why == EVADE_REASON_NO_HOSTILES)
{
- if (!ballLightningEnabled && why == EVADE_REASON_NO_HOSTILES)
- {
- ballLightningEnabled = true;
- return; // try again
- }
- if (events.IsInPhase(PHASE_TRANSITION) || (events.IsInPhase(PHASE_THADDIUS) && me->IsAlive()))
- BeginResetEncounter();
+ ballLightningEnabled = true;
+ return; // try again
}
+ if (events.IsInPhase(PHASE_TRANSITION) || (events.IsInPhase(PHASE_THADDIUS) && me->IsAlive()))
+ BeginResetEncounter();
+ }
- bool CanAIAttack(Unit const* who) const override
- {
- if (ballLightningEnabled || me->IsWithinMeleeRange(who))
- return BossAI::CanAIAttack(who);
- else
- return false;
- }
+ bool CanAIAttack(Unit const* who) const override
+ {
+ if (ballLightningEnabled || me->IsWithinMeleeRange(who))
+ return BossAI::CanAIAttack(who);
+ else
+ return false;
+ }
- void JustRespawned() override
- {
- if (events.IsInPhase(PHASE_RESETTING))
- ResetEncounter();
- }
+ void JustAppeared() override
+ {
+ if (instance->GetBossState(BOSS_THADDIUS) != DONE)
+ ResetEncounter();
+ }
- void JustDied(Unit* /*killer*/) override
- {
- _JustDied();
- me->setActive(false);
- if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG)))
- stalagg->setActive(false);
- if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN)))
- feugen->setActive(false);
- Talk(SAY_DEATH);
- }
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ me->setActive(false);
+ if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG)))
+ stalagg->setActive(false);
+ if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN)))
+ feugen->setActive(false);
+ Talk(SAY_DEATH);
+ }
- void DoAction(int32 action) override
+ void DoAction(int32 action) override
+ {
+ switch (action)
{
- switch (action)
- {
- case ACTION_RESET_ENCOUNTER_TIMER:
- if (events.IsInPhase(PHASE_RESETTING))
- ResetEncounter();
- break;
- case ACTION_FEUGEN_RESET:
- case ACTION_STALAGG_RESET:
- if (!events.IsInPhase(PHASE_NOT_ENGAGED) && !events.IsInPhase(PHASE_RESETTING))
- BeginResetEncounter();
- break;
- case ACTION_FEUGEN_AGGRO:
- case ACTION_STALAGG_AGGRO:
- if (events.IsInPhase(PHASE_RESETTING))
- {
- BeginResetEncounter();
- return;
- }
- if (!events.IsInPhase(PHASE_NOT_ENGAGED))
- return;
- events.SetPhase(PHASE_PETS);
-
- shockingEligibility = true;
-
- if (!instance->CheckRequiredBosses(BOSS_THADDIUS))
- {
- BeginResetEncounter();
- return;
- }
- instance->SetBossState(BOSS_THADDIUS, IN_PROGRESS);
+ case ACTION_FEUGEN_RESET:
+ case ACTION_STALAGG_RESET:
+ if (!events.IsInPhase(PHASE_NOT_ENGAGED))
+ BeginResetEncounter();
+ break;
+ case ACTION_FEUGEN_AGGRO:
+ case ACTION_STALAGG_AGGRO:
+ if (!events.IsInPhase(PHASE_NOT_ENGAGED))
+ return;
+ events.SetPhase(PHASE_PETS);
- me->setActive(true);
- DoZoneInCombat();
- if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG)))
- stalagg->setActive(true);
- if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN)))
- feugen->setActive(true);
- break;
- case ACTION_FEUGEN_DIED:
- if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN)))
- feugen->AI()->DoAction(ACTION_FEUGEN_REVIVING_FX);
- feugenAlive = false;
- if (stalaggAlive)
- events.ScheduleEvent(EVENT_REVIVE_FEUGEN, Seconds(5), 0, PHASE_PETS);
- else
- Transition();
+ shockingEligibility = true;
- break;
- case ACTION_STALAGG_DIED:
- if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG)))
- stalagg->AI()->DoAction(ACTION_STALAGG_REVIVING_FX);
- stalaggAlive = false;
- if (feugenAlive)
- events.ScheduleEvent(EVENT_REVIVE_STALAGG, Seconds(5), 0, PHASE_PETS);
- else
- Transition();
-
- break;
+ if (!instance->CheckRequiredBosses(BOSS_THADDIUS))
+ {
+ BeginResetEncounter();
+ return;
+ }
+ instance->SetBossState(BOSS_THADDIUS, IN_PROGRESS);
+
+ me->setActive(true);
+ DoZoneInCombat();
+ if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG)))
+ stalagg->setActive(true);
+ if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN)))
+ feugen->setActive(true);
+ break;
+ case ACTION_FEUGEN_DIED:
+ if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN)))
+ feugen->AI()->DoAction(ACTION_FEUGEN_REVIVING_FX);
+ feugenAlive = false;
+ if (stalaggAlive)
+ events.ScheduleEvent(EVENT_REVIVE_FEUGEN, Seconds(5), 0, PHASE_PETS);
+ else
+ Transition();
+
+ break;
+ case ACTION_STALAGG_DIED:
+ if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG)))
+ stalagg->AI()->DoAction(ACTION_STALAGG_REVIVING_FX);
+ stalaggAlive = false;
+ if (feugenAlive)
+ events.ScheduleEvent(EVENT_REVIVE_STALAGG, Seconds(5), 0, PHASE_PETS);
+ else
+ Transition();
- case ACTION_POLARITY_CROSSED:
- shockingEligibility = false;
- break;
- default:
- break;
- }
- }
+ break;
- uint32 GetData(uint32 id) const override
- {
- return (id == DATA_POLARITY_CROSSED && shockingEligibility) ? 1u : 0u;
+ case ACTION_POLARITY_CROSSED:
+ shockingEligibility = false;
+ break;
+ default:
+ break;
}
+ }
- void Transition() // initiate transition between pet phase and thaddius phase
- {
- events.SetPhase(PHASE_TRANSITION);
-
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
-
- events.ScheduleEvent(EVENT_TRANSITION_1, Seconds(10), 0, PHASE_TRANSITION);
- events.ScheduleEvent(EVENT_TRANSITION_2, Seconds(12), 0, PHASE_TRANSITION);
- events.ScheduleEvent(EVENT_TRANSITION_3, Seconds(14), 0, PHASE_TRANSITION);
- }
+ uint32 GetData(uint32 id) const override
+ {
+ return (id == DATA_POLARITY_CROSSED && shockingEligibility) ? 1u : 0u;
+ }
- void BeginResetEncounter(bool initial = false)
- {
- if (instance->GetBossState(BOSS_THADDIUS) == DONE)
- return;
- if (events.IsInPhase(PHASE_RESETTING))
- return;
+ void Transition() // initiate transition between pet phase and thaddius phase
+ {
+ events.SetPhase(PHASE_TRANSITION);
- // remove polarity shift debuffs on reset
- instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_POSITIVE_CHARGE_APPLY);
- instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_NEGATIVE_CHARGE_APPLY);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->DespawnOrUnsummon();
- me->SetRespawnTime(initial ? 5 : 30);
+ events.ScheduleEvent(EVENT_TRANSITION_1, Seconds(10), 0, PHASE_TRANSITION);
+ events.ScheduleEvent(EVENT_TRANSITION_2, Seconds(12), 0, PHASE_TRANSITION);
+ events.ScheduleEvent(EVENT_TRANSITION_3, Seconds(14), 0, PHASE_TRANSITION);
+ }
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED);
- me->SetImmuneToPC(true);
- events.SetPhase(PHASE_RESETTING);
- if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN)))
- feugen->AI()->DoAction(ACTION_BEGIN_RESET_ENCOUNTER);
- if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG)))
- stalagg->AI()->DoAction(ACTION_BEGIN_RESET_ENCOUNTER);
+ void BeginResetEncounter()
+ {
+ if (instance->GetBossState(BOSS_THADDIUS) == DONE)
+ return;
+
+ // remove polarity shift debuffs on reset
+ instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_POSITIVE_CHARGE_APPLY);
+ instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_NEGATIVE_CHARGE_APPLY);
+
+ me->DespawnOrUnsummon(0, Seconds(30));
+
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED);
+ me->SetImmuneToPC(true);
+ me->setActive(false);
+ if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN)))
+ feugen->AI()->DoAction(ACTION_BEGIN_RESET_ENCOUNTER);
+ if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG)))
+ stalagg->AI()->DoAction(ACTION_BEGIN_RESET_ENCOUNTER);
+ }
- me->setActive(false);
- }
+ void ResetEncounter()
+ {
+ feugenAlive = true;
+ stalaggAlive = true;
- void ResetEncounter()
- {
- feugenAlive = true;
- stalaggAlive = true;
+ _Reset();
+ events.SetPhase(PHASE_NOT_ENGAGED);
+ me->SetReactState(REACT_PASSIVE);
- _Reset();
- events.SetPhase(PHASE_NOT_ENGAGED);
- me->SetReactState(REACT_PASSIVE);
+ // @todo these guys should really be moved to a summon group - this is merely a hack to make them work in dynamic_spawning
+ instance->instance->RemoveRespawnTime(SPAWN_TYPE_CREATURE, 130958, true); // Stalagg
+ instance->instance->RemoveRespawnTime(SPAWN_TYPE_CREATURE, 130959, true); // Feugen
+ }
- if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN)))
- feugen->AI()->DoAction(ACTION_RESET_ENCOUNTER);
- if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG)))
- stalagg->AI()->DoAction(ACTION_RESET_ENCOUNTER);
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (events.IsInPhase(PHASE_NOT_ENGAGED))
+ return;
+ if (events.IsInPhase(PHASE_THADDIUS) && !UpdateVictim())
+ return;
- void UpdateAI(uint32 diff) override
+ events.Update(diff);
+ while (uint32 eventId = events.ExecuteEvent())
{
- if (events.IsInPhase(PHASE_NOT_ENGAGED))
- return;
- if (events.IsInPhase(PHASE_THADDIUS) && !UpdateVictim())
- return;
-
- events.Update(diff);
- while (uint32 eventId = events.ExecuteEvent())
+ switch (eventId)
{
- switch (eventId)
- {
- case EVENT_REVIVE_FEUGEN:
- feugenAlive = true;
- if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN)))
- feugen->AI()->DoAction(ACTION_FEUGEN_REVIVED);
- break;
- case EVENT_REVIVE_STALAGG:
- stalaggAlive = true;
- if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG)))
- stalagg->AI()->DoAction(ACTION_STALAGG_REVIVED);
- break;
- case EVENT_TRANSITION_1: // tesla coils overload
- if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN)))
- feugen->AI()->DoAction(ACTION_TRANSITION);
- if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG)))
- stalagg->AI()->DoAction(ACTION_TRANSITION);
- break;
- case EVENT_TRANSITION_2: // tesla coils shock thaddius
- me->CastSpell(me, SPELL_THADDIUS_SPARK_VISUAL, true);
- if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN)))
- feugen->AI()->DoAction(ACTION_TRANSITION_2);
- if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG)))
- stalagg->AI()->DoAction(ACTION_TRANSITION_2);
- break;
- case EVENT_TRANSITION_3: // thaddius becomes active
- me->CastSpell(me, SPELL_THADDIUS_SPARK_VISUAL, true);
- ballLightningUnlocked = false;
- me->RemoveAura(SPELL_THADDIUS_INACTIVE_VISUAL);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
- me->SetImmuneToPC(false);
- me->SetReactState(REACT_AGGRESSIVE);
-
- DoZoneInCombat();
- if (Unit* closest = SelectTarget(SELECT_TARGET_MINDISTANCE, 0, 500.0f))
- AttackStart(closest);
- else // if there is no nearest target, then there is no target, meaning we should reset
- {
- BeginResetEncounter();
- return;
- }
+ case EVENT_REVIVE_FEUGEN:
+ feugenAlive = true;
+ if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN)))
+ feugen->AI()->DoAction(ACTION_FEUGEN_REVIVED);
+ break;
+ case EVENT_REVIVE_STALAGG:
+ stalaggAlive = true;
+ if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG)))
+ stalagg->AI()->DoAction(ACTION_STALAGG_REVIVED);
+ break;
+ case EVENT_TRANSITION_1: // tesla coils overload
+ if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN)))
+ feugen->AI()->DoAction(ACTION_TRANSITION);
+ if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG)))
+ stalagg->AI()->DoAction(ACTION_TRANSITION);
+ break;
+ case EVENT_TRANSITION_2: // tesla coils shock thaddius
+ me->CastSpell(me, SPELL_THADDIUS_SPARK_VISUAL, true);
+ if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN)))
+ feugen->AI()->DoAction(ACTION_TRANSITION_2);
+ if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG)))
+ stalagg->AI()->DoAction(ACTION_TRANSITION_2);
+ break;
+ case EVENT_TRANSITION_3: // thaddius becomes active
+ me->CastSpell(me, SPELL_THADDIUS_SPARK_VISUAL, true);
+ ballLightningUnlocked = false;
+ me->RemoveAura(SPELL_THADDIUS_INACTIVE_VISUAL);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
+ me->SetImmuneToPC(false);
+ me->SetReactState(REACT_AGGRESSIVE);
- if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN)))
- feugen->AI()->DoAction(ACTION_TRANSITION_3);
- if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG)))
- stalagg->AI()->DoAction(ACTION_TRANSITION_3);
+ DoZoneInCombat();
+ if (Unit* closest = SelectTarget(SELECT_TARGET_MINDISTANCE, 0, 500.0f))
+ AttackStart(closest);
+ else // if there is no nearest target, then there is no target, meaning we should reset
+ {
+ BeginResetEncounter();
+ return;
+ }
- events.SetPhase(PHASE_THADDIUS);
+ if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN)))
+ feugen->AI()->DoAction(ACTION_TRANSITION_3);
+ if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG)))
+ stalagg->AI()->DoAction(ACTION_TRANSITION_3);
- Talk(SAY_AGGRO);
+ events.SetPhase(PHASE_THADDIUS);
- events.ScheduleEvent(EVENT_ENABLE_BALL_LIGHTNING, Seconds(5), 0, PHASE_THADDIUS);
- events.ScheduleEvent(EVENT_SHIFT, Seconds(10), 0, PHASE_THADDIUS);
- events.ScheduleEvent(EVENT_CHAIN, randtime(Seconds(10), Seconds(20)), 0, PHASE_THADDIUS);
- events.ScheduleEvent(EVENT_BERSERK, Minutes(6), 0, PHASE_THADDIUS);
+ Talk(SAY_AGGRO);
- break;
- case EVENT_ENABLE_BALL_LIGHTNING:
- ballLightningUnlocked = true;
- break;
- case EVENT_SHIFT:
- me->CastStop(); // shift overrides all other spells
- DoCastAOE(SPELL_POLARITY_SHIFT);
- events.ScheduleEvent(EVENT_SHIFT_TALK, Seconds(3), PHASE_THADDIUS);
- events.ScheduleEvent(EVENT_SHIFT, Seconds(30), PHASE_THADDIUS);
- break;
- case EVENT_SHIFT_TALK:
- Talk(SAY_ELECT);
- Talk(EMOTE_POLARITY_SHIFTED);
- break;
- case EVENT_CHAIN:
- if (me->FindCurrentSpellBySpellId(SPELL_POLARITY_SHIFT)) // delay until shift is over
- events.Repeat(Seconds(3));
- else
- {
- me->CastStop();
- DoCastVictim(SPELL_CHAIN_LIGHTNING);
- events.Repeat(randtime(Seconds(10), Seconds(20)));
- }
- break;
- case EVENT_BERSERK:
+ events.ScheduleEvent(EVENT_ENABLE_BALL_LIGHTNING, Seconds(5), 0, PHASE_THADDIUS);
+ events.ScheduleEvent(EVENT_SHIFT, Seconds(10), 0, PHASE_THADDIUS);
+ events.ScheduleEvent(EVENT_CHAIN, randtime(Seconds(10), Seconds(20)), 0, PHASE_THADDIUS);
+ events.ScheduleEvent(EVENT_BERSERK, Minutes(6), 0, PHASE_THADDIUS);
+
+ break;
+ case EVENT_ENABLE_BALL_LIGHTNING:
+ ballLightningUnlocked = true;
+ break;
+ case EVENT_SHIFT:
+ me->CastStop(); // shift overrides all other spells
+ DoCastAOE(SPELL_POLARITY_SHIFT);
+ events.ScheduleEvent(EVENT_SHIFT_TALK, Seconds(3), PHASE_THADDIUS);
+ events.ScheduleEvent(EVENT_SHIFT, Seconds(30), PHASE_THADDIUS);
+ break;
+ case EVENT_SHIFT_TALK:
+ Talk(SAY_ELECT);
+ Talk(EMOTE_POLARITY_SHIFTED);
+ break;
+ case EVENT_CHAIN:
+ if (me->FindCurrentSpellBySpellId(SPELL_POLARITY_SHIFT)) // delay until shift is over
+ events.Repeat(Seconds(3));
+ else
+ {
me->CastStop();
- DoCast(me, SPELL_BERSERK);
- break;
- default:
- break;
- }
+ DoCastVictim(SPELL_CHAIN_LIGHTNING);
+ events.Repeat(randtime(Seconds(10), Seconds(20)));
+ }
+ break;
+ case EVENT_BERSERK:
+ me->CastStop();
+ DoCast(me, SPELL_BERSERK);
+ break;
+ default:
+ break;
}
- if (events.IsInPhase(PHASE_THADDIUS) && !me->HasUnitState(UNIT_STATE_CASTING) && me->isAttackReady())
+ }
+ if (events.IsInPhase(PHASE_THADDIUS) && !me->HasUnitState(UNIT_STATE_CASTING) && me->isAttackReady())
+ {
+ if (me->IsWithinMeleeRange(me->GetVictim()))
{
- if (me->IsWithinMeleeRange(me->GetVictim()))
- {
- ballLightningEnabled = false;
- DoMeleeAttackIfReady();
- }
- else if (ballLightningUnlocked)
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_BALL_LIGHTNING);
+ ballLightningEnabled = false;
+ DoMeleeAttackIfReady();
}
+ else if (ballLightningUnlocked)
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
+ DoCast(target, SPELL_BALL_LIGHTNING);
}
+ }
- private:
- bool stalaggAlive;
- bool feugenAlive;
- bool ballLightningUnlocked; // whether the initial ball lightning grace period has expired and we should proceed to exterminate with extreme prejudice
- bool ballLightningEnabled; // switch that is flipped to true if we try to evade due to no eligible targets in melee range
- bool shockingEligibility;
- };
-
+ private:
+ bool stalaggAlive;
+ bool feugenAlive;
+ bool ballLightningUnlocked; // whether the initial ball lightning grace period has expired and we should proceed to exterminate with extreme prejudice
+ bool ballLightningEnabled; // switch that is flipped to true if we try to evade due to no eligible targets in melee range
+ bool shockingEligibility;
};
class npc_stalagg : public CreatureScript
@@ -527,7 +494,7 @@ public:
{
if (GameObject* coil = myCoilGO())
coil->SetGoState(GO_STATE_READY);
- me->DespawnOrUnsummon();
+ me->DespawnOrUnsummon(0, Hours(24*7)); // will be force respawned by thaddius
me->setActive(false);
}
@@ -544,9 +511,6 @@ public:
case ACTION_BEGIN_RESET_ENCOUNTER:
BeginResetEncounter();
break;
- case ACTION_RESET_ENCOUNTER:
- ResetEncounter();
- break;
case ACTION_STALAGG_REVIVING_FX:
break;
case ACTION_STALAGG_REVIVED:
@@ -571,7 +535,7 @@ public:
break;
case ACTION_TRANSITION:
me->KillSelf(); // true death
- me->DespawnOrUnsummon();
+ me->DespawnOrUnsummon(0, Hours(24*7));
if (Creature* coil = myCoil())
{
@@ -793,16 +757,10 @@ public:
{
if (GameObject* coil = myCoilGO())
coil->SetGoState(GO_STATE_READY);
- me->DespawnOrUnsummon();
+ me->DespawnOrUnsummon(0, Hours(24*7)); // will be force respawned by thaddius
me->setActive(false);
}
- void ResetEncounter()
- {
- me->Respawn(true);
- Initialize();
- }
-
void DoAction(int32 action) override
{
switch (action)
@@ -810,9 +768,6 @@ public:
case ACTION_BEGIN_RESET_ENCOUNTER:
BeginResetEncounter();
break;
- case ACTION_RESET_ENCOUNTER:
- ResetEncounter();
- break;
case ACTION_FEUGEN_REVIVING_FX:
break;
case ACTION_FEUGEN_REVIVED:
@@ -839,7 +794,7 @@ public:
break;
case ACTION_TRANSITION:
me->KillSelf(); // true death this time around
- me->DespawnOrUnsummon();
+ me->DespawnOrUnsummon(0, Hours(24*7));
if (Creature* coil = myCoil())
{
@@ -1270,20 +1225,19 @@ class spell_thaddius_magnetic_pull : public SpellScriptLoader
}
};
-class at_thaddius_entrance : public AreaTriggerScript
+class at_thaddius_entrance : public OnlyOnceAreaTriggerScript
{
public:
- at_thaddius_entrance() : AreaTriggerScript("at_thaddius_entrance") { }
+ at_thaddius_entrance() : OnlyOnceAreaTriggerScript("at_thaddius_entrance") { }
- bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
+ bool _OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
{
InstanceScript* instance = player->GetInstanceScript();
- if (!instance || instance->GetData(DATA_HAD_THADDIUS_GREET) || instance->GetBossState(BOSS_THADDIUS) == DONE)
+ if (!instance || instance->GetBossState(BOSS_THADDIUS) == DONE)
return true;
if (Creature* thaddius = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_THADDIUS)))
thaddius->AI()->Talk(SAY_GREET);
- instance->SetData(DATA_HAD_THADDIUS_GREET, 1u);
return true;
}
@@ -1303,7 +1257,7 @@ class achievement_thaddius_shocking : public AchievementCriteriaScript
void AddSC_boss_thaddius()
{
- new boss_thaddius();
+ RegisterNaxxramasCreatureAI(boss_thaddius);
new npc_stalagg();
new npc_feugen();
new npc_tesla();
diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp
index f8638a33fa0..3e06319a379 100644
--- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp
@@ -121,9 +121,6 @@ class instance_naxxramas : public InstanceMapScript
LoadDoorData(doorData);
LoadObjectData(nullptr, objectData);
- hadAnubRekhanGreet = false;
- hadFaerlinaGreet = false;
- hadThaddiusGreet = false;
hadSapphironBirth = false;
CurrentWingTaunt = SAY_KELTHUZAD_FIRST_WING_TAUNT;
@@ -279,15 +276,6 @@ class instance_naxxramas : public InstanceMapScript
if (GameObject* gate = instance->GetGameObject(GothikGateGUID))
gate->SetGoState(GOState(value));
break;
- case DATA_HAD_ANUBREKHAN_GREET:
- hadAnubRekhanGreet = (value == 1u);
- break;
- case DATA_HAD_FAERLINA_GREET:
- hadFaerlinaGreet = (value == 1u);
- break;
- case DATA_HAD_THADDIUS_GREET:
- hadThaddiusGreet = (value == 1u);
- break;
case DATA_HAD_SAPPHIRON_BIRTH:
hadSapphironBirth = (value == 1u);
break;
@@ -300,12 +288,6 @@ class instance_naxxramas : public InstanceMapScript
{
switch (id)
{
- case DATA_HAD_ANUBREKHAN_GREET:
- return hadAnubRekhanGreet ? 1u : 0u;
- case DATA_HAD_FAERLINA_GREET:
- return hadFaerlinaGreet ? 1u : 0u;
- case DATA_HAD_THADDIUS_GREET:
- return hadThaddiusGreet ? 1u : 0u;
case DATA_HAD_SAPPHIRON_BIRTH:
return hadSapphironBirth ? 1u : 0u;
default:
@@ -625,9 +607,6 @@ class instance_naxxramas : public InstanceMapScript
ObjectGuid PortalsGUID[4];
ObjectGuid KelthuzadDoorGUID;
ObjectGuid LichKingGUID;
- bool hadAnubRekhanGreet;
- bool hadFaerlinaGreet;
- bool hadThaddiusGreet;
bool hadSapphironBirth;
uint8 CurrentWingTaunt;
diff --git a/src/server/scripts/Northrend/Naxxramas/naxxramas.h b/src/server/scripts/Northrend/Naxxramas/naxxramas.h
index 2813e338245..64e313fea59 100644
--- a/src/server/scripts/Northrend/Naxxramas/naxxramas.h
+++ b/src/server/scripts/Northrend/Naxxramas/naxxramas.h
@@ -47,9 +47,6 @@ enum NAXEncounter
enum NAXData
{
DATA_GOTHIK_GATE,
- DATA_HAD_ANUBREKHAN_GREET,
- DATA_HAD_FAERLINA_GREET,
- DATA_HAD_THADDIUS_GREET,
DATA_HAD_SAPPHIRON_BIRTH,
DATA_HORSEMEN_CHECK_ACHIEVEMENT_CREDIT,
@@ -224,5 +221,6 @@ inline AI* GetNaxxramasAI(T* obj)
{
return GetInstanceAI<AI>(obj, NaxxramasScriptName);
}
+#define RegisterNaxxramasCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetNaxxramasAI)
#endif
diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
index 8e51d79a87b..a7ea5b57fb0 100644
--- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
+++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
@@ -2142,7 +2142,7 @@ class spell_alexstrasza_bunny_destroy_platform_event : public SpellScriptLoader
void HandleScript(SpellEffIndex /*effIndex*/)
{
- GetCaster()->CastSpell((Unit*)nullptr, SPELL_SUMMON_RED_DRAGON_BUDDY_F_CAST);
+ GetCaster()->CastSpell(nullptr, SPELL_SUMMON_RED_DRAGON_BUDDY_F_CAST);
}
void Register() override
@@ -2271,7 +2271,7 @@ class spell_malygos_surge_of_power_warning_selector_25 : public SpellScriptLoade
void ExecuteMainSpell()
{
- GetCaster()->ToCreature()->CastSpell((Unit*)nullptr, SPELL_SURGE_OF_POWER_PHASE_3_25);
+ GetCaster()->ToCreature()->CastSpell(nullptr, SPELL_SURGE_OF_POWER_PHASE_3_25);
}
void Register() override
diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp
index 338b273808f..a98fadd56d9 100644
--- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp
+++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp
@@ -156,7 +156,7 @@ class spell_krystallus_shatter : public SpellScriptLoader
if (Unit* target = GetHitUnit())
{
target->RemoveAurasDueToSpell(SPELL_STONED);
- target->CastSpell((Unit*)nullptr, SPELL_SHATTER_EFFECT, true);
+ target->CastSpell(nullptr, SPELL_SHATTER_EFFECT, true);
}
}
diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp
index fc54e6fec54..80d59691fb5 100644
--- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp
+++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp
@@ -271,9 +271,9 @@ class npc_brann_hos : public CreatureScript
public:
npc_brann_hos() : CreatureScript("npc_brann_hos") { }
- struct npc_brann_hosAI : public npc_escortAI
+ struct npc_brann_hosAI : public EscortAI
{
- npc_brann_hosAI(Creature* creature) : npc_escortAI(creature)
+ npc_brann_hosAI(Creature* creature) : EscortAI(creature)
{
Initialize();
instance = creature->GetInstanceScript();
@@ -326,7 +326,7 @@ public:
lDwarfGUIDList.clear();
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
index 69d5fa4d2fb..868e337933d 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
@@ -254,7 +254,7 @@ class ActivateLivingConstellation : public BasicEvent
if (!_instance || _instance->GetBossState(BOSS_ALGALON) != IN_PROGRESS)
return true; // delete event
- _owner->CastSpell((Unit*)nullptr, SPELL_TRIGGER_3_ADDS, TRIGGERED_FULL_MASK);
+ _owner->CastSpell(nullptr, SPELL_TRIGGER_3_ADDS, TRIGGERED_FULL_MASK);
_owner->m_Events.AddEvent(this, execTime + urand(45000, 50000));
return false;
}
@@ -273,7 +273,7 @@ class CosmicSmashDamageEvent : public BasicEvent
bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override
{
- _caster->CastSpell((Unit*)nullptr, SPELL_COSMIC_SMASH_TRIGGERED, TRIGGERED_FULL_MASK);
+ _caster->CastSpell(nullptr, SPELL_COSMIC_SMASH_TRIGGERED, TRIGGERED_FULL_MASK);
return true;
}
@@ -290,7 +290,7 @@ class SummonUnleashedDarkMatter : public BasicEvent
bool Execute(uint64 execTime, uint32 /*diff*/) override
{
- _caster->CastSpell((Unit*)nullptr, SPELL_SUMMON_UNLEASHED_DARK_MATTER, TRIGGERED_FULL_MASK);
+ _caster->CastSpell(nullptr, SPELL_SUMMON_UNLEASHED_DARK_MATTER, TRIGGERED_FULL_MASK);
_caster->m_Events.AddEvent(this, execTime + 30000);
return false;
}
@@ -474,9 +474,9 @@ class boss_algalon_the_observer : public CreatureScript
break;
case NPC_BLACK_HOLE:
summon->SetReactState(REACT_PASSIVE);
- summon->CastSpell((Unit*)nullptr, SPELL_BLACK_HOLE_TRIGGER, TRIGGERED_FULL_MASK);
+ summon->CastSpell(nullptr, SPELL_BLACK_HOLE_TRIGGER, TRIGGERED_FULL_MASK);
summon->CastSpell(summon, SPELL_CONSTELLATION_PHASE_TRIGGER, TRIGGERED_FULL_MASK);
- summon->CastSpell((Unit*)nullptr, SPELL_BLACK_HOLE_EXPLOSION);
+ summon->CastSpell(nullptr, SPELL_BLACK_HOLE_EXPLOSION);
summon->CastSpell(summon, SPELL_SUMMON_VOID_ZONE_VISUAL, TRIGGERED_FULL_MASK);
break;
case NPC_ALGALON_VOID_ZONE_VISUAL_STALKER:
@@ -787,7 +787,7 @@ class npc_living_constellation : public CreatureScript
me->DespawnOrUnsummon(1);
if (InstanceScript* instance = me->GetInstanceScript())
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, EVENT_ID_SUPERMASSIVE_START);
- caster->CastSpell((Unit*)nullptr, SPELL_BLACK_HOLE_CREDIT, TRIGGERED_FULL_MASK);
+ caster->CastSpell(nullptr, SPELL_BLACK_HOLE_CREDIT, TRIGGERED_FULL_MASK);
caster->ToCreature()->DespawnOrUnsummon(1);
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp
index aa6e8e955b4..d2e8549a110 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp
@@ -17,556 +17,646 @@
#include "ScriptMgr.h"
#include "InstanceScript.h"
+#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "ScriptedCreature.h"
+#include "SpellAuras.h"
#include "SpellScript.h"
#include "ulduar.h"
enum AuriayaSpells
{
// Auriaya
- SPELL_SENTINEL_BLAST = 64389,
- SPELL_SONIC_SCREECH = 64422,
- SPELL_TERRIFYING_SCREECH = 64386,
- SPELL_SUMMON_SWARMING_GUARDIAN = 64396,
- SPELL_ACTIVATE_DEFENDER = 64449,
- SPELL_DEFENDER_TRIGGER = 64448,
- SPELL_SUMMON_DEFENDER = 64447,
- SPELL_BERSERK = 47008,
+ SPELL_SENTINEL_BLAST = 64389,
+ SPELL_SONIC_SCREECH = 64422,
+ SPELL_TERRIFYING_SCREECH = 64386,
+ SPELL_SUMMON_SWARMING_GUARDIAN = 64396,
+ SPELL_ACTIVATE_DEFENDER = 64449,
+ SPELL_DEFENDER_TRIGGER = 64448,
+ SPELL_BERSERK = 47008,
+ SPELL_INSTAKILL_ARACHNOPOD = 64900,
// Feral Defender
- SPELL_FERAL_RUSH = 64496,
- SPELL_FERAL_POUNCE = 64478,
- SPELL_SEEPING_ESSENCE = 64458,
- SPELL_SUMMON_ESSENCE = 64457,
- SPELL_FERAL_ESSENCE = 64455,
+ SPELL_FERAL_RUSH = 64496,
+ SPELL_FERAL_RUSH_2 = 64489,
+ SPELL_FERAL_POUNCE = 64478,
+ SPELL_SUMMON_ESSENCE = 64457,
+ SPELL_FERAL_ESSENCE = 64455,
+ SPELL_SHADOW_PAWS = 64479,
+ SPELL_REDUCE_CRITCAL = 64481,
+ SPELL_RANDOM_AGRO_PERIODIC = 61906,
+ SPELL_PERMANENT_FEIGN_DEATH = 58951,
+ SPELL_FERAL_ESSENCE_APPLICATION_REMOVAL = 64456,
+ SPELL_CLEAR_ALL_DEBUFFS = 34098,
+ SPELL_DROWNED_STATE = 64462,
+ SPELL_FULL_HEAL = 64460,
+
+ // Seeping Essence Stalker
+ SPELL_SEEPING_ESSENCE = 64458,
// Sanctum Sentry
- SPELL_SAVAGE_POUNCE = 64666,
- SPELL_RIP_FLESH = 64375,
- SPELL_STRENGHT_PACK = 64369,
-};
+ SPELL_SAVAGE_POUNCE = 64666,
+ SPELL_RIP_FLESH = 64375,
+ SPELL_STRENGHT_OF_THE_PACK = 64369,
-enum AuriayaNPCs
-{
- NPC_SANCTUM_SENTRY = 34014,
- NPC_FERAL_DEFENDER = 34035,
- NPC_FERAL_DEFENDER_TRIGGER = 34096,
- NPC_SEEPING_TRIGGER = 34098,
+ // Swarming Guardian
+ SPELL_AGRO_CREATOR = 63709,
+ SPELL_POUNCE = 64399
};
enum AuriayaEvents
{
// Auriaya
- EVENT_SCREECH = 1,
- EVENT_BLAST = 2,
- EVENT_TERRIFYING = 3,
- EVENT_SUMMON = 4,
- EVENT_DEFENDER = 5,
- EVENT_ACTIVATE_DEFENDER = 6,
- EVENT_RESPAWN_DEFENDER = 7,
- EVENT_BERSERK = 8,
+ EVENT_SONIC_SCREECH = 1,
+ EVENT_BLAST,
+ EVENT_TERRIFYING_SCREECH,
+ EVENT_SWARNING_GUARDIAN,
+ EVENT_SUMMON_DEFENDER,
+ EVENT_ACTIVATE_DEFENDER,
+ EVENT_BERSERK,
// Sanctum Sentry
- EVENT_RIP = 9,
- EVENT_POUNCE = 10,
+ EVENT_RIP,
+ EVENT_SAVAGE_POUNCE,
// Feral Defender
- EVENT_FERAL_POUNCE = 11,
- EVENT_RUSH = 12,
+ EVENT_FERAL_POUNCE,
+ EVENT_RUSH,
+ EVENT_START_COMBAT,
+ EVENT_RESPAWN_DEFENDER,
+ EVENT_RESPAWN_DEFENDER_2,
+ EVENT_RESPAWN_DEFENDER_3
};
enum AuriayaYells
{
- SAY_AGGRO = 0,
- SAY_SLAY = 1,
- SAY_DEATH = 2,
- SAY_BERSERK = 3,
- EMOTE_FEAR = 4,
- EMOTE_DEFENDER = 5
+ SAY_AGGRO = 0,
+ SAY_SLAY = 1,
+ SAY_BERSERK = 2,
+ EMOTE_FEAR = 3,
+ EMOTE_DEFENDER = 4
};
enum AuriayaActions
{
- ACTION_CRAZY_CAT_LADY = 0,
- ACTION_RESPAWN_DEFENDER
+ ACTION_CRAZY_CAT_LADY = 0,
+ ACTION_DEFENDER_DIED
};
-#define SENTRY_NUMBER RAID_MODE<uint8>(2, 4)
-
-enum Mis
+enum Misc
{
- DATA_NINE_LIVES = 30763077,
- DATA_CRAZY_CAT_LADY = 30063007
+ DATA_NINE_LIVES = 30763077,
+ DATA_CRAZY_CAT_LADY = 30063007,
+ PHASE_NONE = 1,
+ PHASE_COMBAT = 2,
+ SUMMON_GROUP_10_MAN = 1,
+ SUMMON_GROUP_25_MAN = 2,
+ AURIAYA_DEATH_SOUNDID = 15476,
+ NPC_SANCTUM_SENTRY = 34014
};
-class boss_auriaya : public CreatureScript
+class CatsTargetSelector
{
- public:
- boss_auriaya() : CreatureScript("boss_auriaya") { }
+public:
+ CatsTargetSelector(Unit const* unit, float minDist, float maxDist) : _me(unit), _minDist(minDist), _maxDist(maxDist) { }
+
+ bool operator()(Unit* unit) const
+ {
+ float dist = _me->GetDistance(unit);
+ return unit->GetTypeId() == TYPEID_PLAYER && dist >= _minDist && dist < _maxDist && _me->IsWithinLOSInMap(unit);
+ }
+
+private:
+ Unit const* _me;
+ float _minDist;
+ float _maxDist;
+};
- struct boss_auriayaAI : public BossAI
+struct boss_auriaya : public BossAI
+{
+ boss_auriaya(Creature* creature) : BossAI(creature, BOSS_AURIAYA), _crazyCatLady(true), _nineLives(false) { }
+
+ void Reset() override
+ {
+ _Reset();
+ _crazyCatLady = true;
+ _nineLives = false;
+ HandleCats(true);
+ }
+
+ void HandleCats(bool isResetting)
+ {
+ std::list<Creature*> catList;
+ me->GetCreatureListWithEntryInGrid(catList, NPC_SANCTUM_SENTRY, 500.0f);
+ for (std::list<Creature*>::const_iterator itr = catList.begin(); itr != catList.end(); ++itr)
{
- boss_auriayaAI(Creature* creature) : BossAI(creature, BOSS_AURIAYA)
- {
- Initialize();
- }
-
- void Initialize()
- {
- DefenderGUID.Clear();
- defenderLives = 8;
- crazyCatLady = true;
- nineLives = false;
- }
-
- void Reset() override
- {
- _Reset();
- Initialize();
- }
-
- void EnterCombat(Unit* /*who*/) override
- {
- _EnterCombat();
- Talk(SAY_AGGRO);
-
- events.ScheduleEvent(EVENT_SCREECH, urand(45000, 65000));
- events.ScheduleEvent(EVENT_BLAST, urand(20000, 25000));
- events.ScheduleEvent(EVENT_TERRIFYING, urand(20000, 30000));
- events.ScheduleEvent(EVENT_DEFENDER, urand(40000, 55000));
- events.ScheduleEvent(EVENT_SUMMON, urand(45000, 55000));
- events.ScheduleEvent(EVENT_BERSERK, 600000);
- }
-
- void KilledUnit(Unit* who) override
- {
- if (who->GetTypeId() == TYPEID_PLAYER)
- Talk(SAY_SLAY);
- }
-
- void JustSummoned(Creature* summoned) override
- {
- summons.Summon(summoned);
-
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
- {
- summoned->AI()->AttackStart(target);
- AddThreat(target, 250.0f, summoned);
- DoZoneInCombat(summoned);
- }
-
- if (summoned->GetEntry() == NPC_FERAL_DEFENDER)
- {
- if (!summoned->IsInCombat() && me->GetVictim())
- summoned->AI()->AttackStart(me->GetVictim());
- summoned->SetAuraStack(SPELL_FERAL_ESSENCE, summoned, 9);
- DefenderGUID = summoned->GetGUID();
- DoZoneInCombat(summoned);
- }
- }
-
- void DoAction(int32 action) override
- {
- switch (action)
- {
- case ACTION_CRAZY_CAT_LADY:
- SetData(DATA_CRAZY_CAT_LADY, 0);
- break;
- case ACTION_RESPAWN_DEFENDER:
- --defenderLives;
- if (!defenderLives)
- {
- SetData(DATA_NINE_LIVES, 1);
- break;
- }
- events.ScheduleEvent(EVENT_RESPAWN_DEFENDER, 30000);
- break;
- default:
- break;
- }
- }
-
- uint32 GetData(uint32 type) const override
- {
- switch (type)
- {
- case DATA_NINE_LIVES:
- return nineLives ? 1 : 0;
- case DATA_CRAZY_CAT_LADY:
- return crazyCatLady ? 1 : 0;
- }
+ if (isResetting)
+ (*itr)->Respawn();
+ else
+ (*itr)->DespawnOrUnsummon();
+ }
+ }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _EnterCombat();
+ Talk(SAY_AGGRO);
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
+ events.ScheduleEvent(EVENT_SONIC_SCREECH, Seconds(48));
+ events.ScheduleEvent(EVENT_TERRIFYING_SCREECH, Seconds(38));
+ events.ScheduleEvent(EVENT_SUMMON_DEFENDER, Seconds(60));
+ events.ScheduleEvent(EVENT_SWARNING_GUARDIAN, Seconds(51));
+ events.ScheduleEvent(EVENT_BERSERK, Minutes(10));
+ }
+
+ void KilledUnit(Unit* who) override
+ {
+ if (who->GetTypeId() == TYPEID_PLAYER && roll_chance_i(50))
+ Talk(SAY_SLAY);
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case ACTION_CRAZY_CAT_LADY:
+ _crazyCatLady = false;
+ break;
+ case ACTION_DEFENDER_DIED:
+ _nineLives = true;
+ break;
+ default:
+ break;
+ }
+ }
+ uint32 GetData(uint32 type) const override
+ {
+ switch (type)
+ {
+ case DATA_NINE_LIVES:
+ return _nineLives ? 1 : 0;
+ case DATA_CRAZY_CAT_LADY:
+ return _crazyCatLady ? 1 : 0;
+ default:
return 0;
- }
-
- void SetData(uint32 id, uint32 data) override
- {
- switch (id)
- {
- case DATA_NINE_LIVES:
- nineLives = data ? true : false;
- break;
- case DATA_CRAZY_CAT_LADY:
- crazyCatLady = data ? true : false;
- break;
- }
- }
-
- void JustDied(Unit* /*killer*/) override
+ }
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ DoPlaySoundToSet(me, AURIAYA_DEATH_SOUNDID);
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ HandleCats(false);
+ }
+
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ summons.DespawnAll();
+ _DespawnAtEvade(Seconds(5));
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- _JustDied();
- Talk(SAY_DEATH);
+ case EVENT_SONIC_SCREECH:
+ DoCastVictim(SPELL_SONIC_SCREECH);
+ events.Repeat(Seconds(22), Seconds(30));
+ break;
+ case EVENT_TERRIFYING_SCREECH:
+ Talk(EMOTE_FEAR);
+ DoCastSelf(SPELL_TERRIFYING_SCREECH);
+ events.ScheduleEvent(EVENT_BLAST, Milliseconds(1));
+ events.Repeat(Seconds(36), Seconds(45));
+ break;
+ case EVENT_BLAST:
+ DoCastAOE(SPELL_SENTINEL_BLAST);
+ break;
+ case EVENT_SUMMON_DEFENDER:
+ Talk(EMOTE_DEFENDER);
+ DoCastSelf(SPELL_DEFENDER_TRIGGER);
+ events.ScheduleEvent(EVENT_ACTIVATE_DEFENDER, Seconds(2));
+ break;
+ case EVENT_ACTIVATE_DEFENDER:
+ DoCastSelf(SPELL_ACTIVATE_DEFENDER);
+ break;
+ case EVENT_SWARNING_GUARDIAN:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
+ DoCast(target, SPELL_SUMMON_SWARMING_GUARDIAN);
+ events.Repeat(Seconds(25), Seconds(45));
+ break;
+ case EVENT_BERSERK:
+ DoCastSelf(SPELL_BERSERK, true);
+ Talk(SAY_BERSERK);
+ break;
+ default:
+ break;
}
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
-
- events.Update(diff);
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_SCREECH:
- DoCast(SPELL_SONIC_SCREECH);
- events.ScheduleEvent(EVENT_SCREECH, urand(40000, 60000));
- break;
- case EVENT_TERRIFYING:
- Talk(EMOTE_FEAR);
- DoCast(SPELL_TERRIFYING_SCREECH);
- events.ScheduleEvent(EVENT_TERRIFYING, urand(20000, 30000));
- break;
- case EVENT_BLAST:
- DoCastAOE(SPELL_SENTINEL_BLAST);
- events.ScheduleEvent(EVENT_BLAST, urand(25000, 35000));
- break;
- case EVENT_DEFENDER:
- Talk(EMOTE_DEFENDER);
- DoCast(SPELL_DEFENDER_TRIGGER);
- if (Creature* trigger = me->FindNearestCreature(NPC_FERAL_DEFENDER_TRIGGER, 15.0f, true))
- DoCast(trigger, SPELL_ACTIVATE_DEFENDER, true);
- break;
- case EVENT_RESPAWN_DEFENDER:
- if (Creature* Defender = ObjectAccessor::GetCreature(*me, DefenderGUID))
- {
- Defender->Respawn();
- if (defenderLives)
- Defender->SetAuraStack(SPELL_FERAL_ESSENCE, Defender, defenderLives);
- Defender->SetInCombatWithZone();
- if (!Defender->IsInCombat())
- Defender->AI()->AttackStart(me->GetVictim());
- events.CancelEvent(EVENT_RESPAWN_DEFENDER);
- }
- break;
- case EVENT_SUMMON:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
- DoCast(target, SPELL_SUMMON_SWARMING_GUARDIAN);
- events.ScheduleEvent(EVENT_SUMMON, urand(30000, 45000));
- break;
- case EVENT_BERSERK:
- DoCast(me, SPELL_BERSERK, true);
- Talk(SAY_BERSERK);
- events.CancelEvent(EVENT_BERSERK);
- break;
- }
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- }
-
- DoMeleeAttackIfReady();
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
- private:
- ObjectGuid DefenderGUID;
- uint8 defenderLives;
- bool crazyCatLady;
- bool nineLives;
- };
+ DoMeleeAttackIfReady();
+ }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetUlduarAI<boss_auriayaAI>(creature);
- }
+private:
+ bool _crazyCatLady;
+ bool _nineLives;
};
-class npc_auriaya_seeping_trigger : public CreatureScript
+struct npc_sanctum_sentry : public ScriptedAI
{
- public:
- npc_auriaya_seeping_trigger() : CreatureScript("npc_auriaya_seeping_trigger") { }
-
- struct npc_auriaya_seeping_triggerAI : public ScriptedAI
+ npc_sanctum_sentry(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
+
+ void Reset() override
+ {
+ DoCastSelf(SPELL_STRENGHT_OF_THE_PACK, true);
+ me->SetWalk(true);
+ }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_RIP, Seconds(6));
+ _events.ScheduleEvent(EVENT_SAVAGE_POUNCE, Milliseconds(1));
+ me->SetWalk(false);
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ if (Creature* auriaya = _instance->GetCreature(BOSS_AURIAYA))
+ auriaya->AI()->DoAction(ACTION_CRAZY_CAT_LADY);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = _events.ExecuteEvent())
{
- npc_auriaya_seeping_triggerAI(Creature* creature) : ScriptedAI(creature)
+ switch (eventId)
{
- instance = me->GetInstanceScript();
- }
-
- void Reset() override
- {
- me->DespawnOrUnsummon(600000);
- DoCast(me, SPELL_SEEPING_ESSENCE);
+ case EVENT_RIP:
+ DoCastVictim(SPELL_RIP_FLESH);
+ _events.Repeat(Seconds(10), Seconds(12));
+ break;
+ case EVENT_SAVAGE_POUNCE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, CatsTargetSelector(me, 10.0f, 15.0f)))
+ {
+ DoCast(target, SPELL_SAVAGE_POUNCE);
+ _events.Repeat(Seconds(10));
+ break;
+ }
+ _events.Repeat(Seconds(1));
+ break;
+ default:
+ break;
}
- void UpdateAI(uint32 /*diff*/) override
- {
- if (instance->GetBossState(BOSS_AURIAYA) != IN_PROGRESS)
- me->DespawnOrUnsummon();
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
- private:
- InstanceScript* instance;
- };
+ DoMeleeAttackIfReady();
+ }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetUlduarAI<npc_auriaya_seeping_triggerAI>(creature);
- }
+private:
+ InstanceScript* _instance;
+ EventMap _events;
};
-class npc_sanctum_sentry : public CreatureScript
+struct npc_feral_defender : public ScriptedAI
{
- public:
- npc_sanctum_sentry() : CreatureScript("npc_sanctum_sentry") { }
-
- struct npc_sanctum_sentryAI : public ScriptedAI
- {
- npc_sanctum_sentryAI(Creature* creature) : ScriptedAI(creature)
- {
- instance = me->GetInstanceScript();
- }
+ npc_feral_defender(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
- void Reset() override
- {
- events.ScheduleEvent(EVENT_RIP, urand(4000, 8000));
- events.ScheduleEvent(EVENT_POUNCE, urand(12000, 15000));
- }
+ void Reset() override
+ {
+ me->SetReactState(REACT_PASSIVE);
+ DoCastSelf(SPELL_SHADOW_PAWS, true);
+ DoCastSelf(SPELL_REDUCE_CRITCAL, true);
+ me->SetAuraStack(SPELL_FERAL_ESSENCE, me, 8);
+ DoCastSelf(SPELL_RANDOM_AGRO_PERIODIC, true);
+ _events.SetPhase(PHASE_NONE);
+ _events.ScheduleEvent(EVENT_START_COMBAT, Seconds(1));
- void EnterCombat(Unit* /*who*/) override
- {
- DoCast(me, SPELL_STRENGHT_PACK, true);
- }
+ if (Creature* auriaya = _instance->GetCreature(BOSS_AURIAYA))
+ auriaya->AI()->JustSummoned(me);
+ }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim() && !_events.IsInPhase(PHASE_NONE))
+ return;
- events.Update(diff);
+ _events.Update(diff);
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_START_COMBAT:
+ _events.SetPhase(PHASE_COMBAT);
+ me->SetReactState(REACT_AGGRESSIVE);
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ AttackStart(target);
+ _events.ScheduleEvent(EVENT_RUSH, Seconds(1));
+ break;
+ case EVENT_RUSH:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, CatsTargetSelector(me, 10.0f, 11.0f)))
{
- case EVENT_RIP:
- DoCastVictim(SPELL_RIP_FLESH);
- events.ScheduleEvent(EVENT_RIP, urand(12000, 15000));
- break;
- case EVENT_POUNCE:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
- {
- AddThreat(target, 100.0f);
- AttackStart(target);
- DoCast(target, SPELL_SAVAGE_POUNCE);
- }
- events.ScheduleEvent(EVENT_POUNCE, urand(12000, 17000));
- break;
- default:
- break;
+ DoCast(target, SPELL_FERAL_RUSH, true);
+ _events.Repeat(Seconds(5));
+ break;
}
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- }
-
- DoMeleeAttackIfReady();
+ _events.Repeat(Seconds(1));
+ break;
+ case EVENT_RESPAWN_DEFENDER:
+ me->SetDisableGravity(true);
+ me->SetHover(true);
+ DoCastSelf(SPELL_DROWNED_STATE, true);
+ _events.ScheduleEvent(EVENT_RESPAWN_DEFENDER_2, Seconds(3));
+ _events.ScheduleEvent(EVENT_RESPAWN_DEFENDER_3, Seconds(5));
+ break;
+ case EVENT_RESPAWN_DEFENDER_2:
+ me->RemoveAurasDueToSpell(SPELL_DROWNED_STATE);
+ break;
+ case EVENT_RESPAWN_DEFENDER_3:
+ me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH);
+ DoCastSelf(SPELL_FULL_HEAL, true);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->SetReactState(REACT_AGGRESSIVE);
+ me->SetDisableGravity(false);
+ me->SetHover(false);
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ AttackStart(target);
+ _events.ScheduleEvent(EVENT_RUSH, Seconds(1));
+ break;
+ default:
+ break;
}
- void JustDied(Unit* /*killer*/) override
- {
- if (Creature* auriaya = instance->GetCreature(BOSS_AURIAYA))
- auriaya->AI()->DoAction(ACTION_CRAZY_CAT_LADY);
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
- private:
- InstanceScript* instance;
- EventMap events;
- };
+ DoMeleeAttackIfReady();
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void DamageTaken(Unit* /*done_by*/, uint32 &damage) override
+ {
+ if (damage >= me->GetHealth() && me->HasAura(SPELL_FERAL_ESSENCE))
{
- return GetUlduarAI<npc_sanctum_sentryAI>(creature);
+ damage = 0;
+ if (!me->HasAura(SPELL_PERMANENT_FEIGN_DEATH))
+ {
+ me->SetReactState(REACT_PASSIVE);
+ me->AttackStop();
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ DoCastSelf(SPELL_PERMANENT_FEIGN_DEATH, true);
+ DoCastSelf(SPELL_FERAL_ESSENCE_APPLICATION_REMOVAL, true);
+ DoCastSelf(SPELL_SUMMON_ESSENCE, true);
+ DoCastSelf(SPELL_CLEAR_ALL_DEBUFFS, true);
+ ResetThreatList();
+ _events.ScheduleEvent(EVENT_RESPAWN_DEFENDER, Seconds(30));
+ _events.CancelEvent(EVENT_RUSH);
+ }
}
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ DoCastSelf(SPELL_SUMMON_ESSENCE, true);
+ if (Creature* auriaya = _instance->GetCreature(BOSS_AURIAYA))
+ auriaya->AI()->DoAction(ACTION_DEFENDER_DIED);
+ }
+
+private:
+ InstanceScript* _instance;
+ EventMap _events;
};
-class npc_feral_defender : public CreatureScript
+struct npc_swarming_guardian : public ScriptedAI
{
- public:
- npc_feral_defender() : CreatureScript("npc_feral_defender") { }
+ npc_swarming_guardian(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
- struct npc_feral_defenderAI : public ScriptedAI
+ void Reset() override
+ {
+ me->SetReactState(REACT_PASSIVE);
+ _scheduler.Schedule(Seconds(1), [this](TaskContext /*context*/)
{
- npc_feral_defenderAI(Creature* creature) : ScriptedAI(creature)
- {
- instance = me->GetInstanceScript();
- }
-
- void Reset() override
- {
- events.ScheduleEvent(EVENT_FERAL_POUNCE, 5000);
- events.ScheduleEvent(EVENT_RUSH, 10000);
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
-
- events.Update(diff);
+ me->SetReactState(REACT_AGGRESSIVE);
+ DoCastSelf(SPELL_AGRO_CREATOR);
+ });
+ if (Creature* auriaya = _instance->GetCreature(BOSS_AURIAYA))
+ auriaya->AI()->JustSummoned(me);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ _scheduler.Update(diff);
+ if (!UpdateVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+
+private:
+ InstanceScript* _instance;
+ TaskScheduler _scheduler;
+};
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+struct npc_seeping_essence_stalker : public ScriptedAI
+{
+ npc_seeping_essence_stalker(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_FERAL_POUNCE:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
- {
- AddThreat(target, 100.0f);
- AttackStart(target);
- DoCast(target, SPELL_FERAL_POUNCE);
- }
- events.ScheduleEvent(EVENT_FERAL_POUNCE, urand(10000, 12000));
- break;
- case EVENT_RUSH:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
- {
- AddThreat(target, 100.0f);
- AttackStart(target);
- DoCast(target, SPELL_FERAL_RUSH);
- }
- events.ScheduleEvent(EVENT_RUSH, urand(10000, 12000));
- break;
- default:
- break;
- }
+ void Reset() override
+ {
+ DoCastSelf(SPELL_SEEPING_ESSENCE);
+ if (Creature* auriaya = _instance->GetCreature(BOSS_AURIAYA))
+ auriaya->AI()->JustSummoned(me);
+ }
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- }
+ void UpdateAI(uint32 /*diff*/) override { }
- DoMeleeAttackIfReady();
- }
+private:
+ InstanceScript* _instance;
+};
- void JustDied(Unit* /*killer*/) override
- {
- DoCast(me, SPELL_SUMMON_ESSENCE);
- if (Creature* auriaya = instance->GetCreature(BOSS_AURIAYA))
- auriaya->AI()->DoAction(ACTION_RESPAWN_DEFENDER);
- }
+// 64381 - Strength of the Pack
+class spell_auriaya_strenght_of_the_pack : public SpellScript
+{
+ PrepareSpellScript(spell_auriaya_strenght_of_the_pack);
- private:
- InstanceScript* instance;
- EventMap events;
- };
+ void FilterTargets(std::list<WorldObject*>& unitList)
+ {
+ unitList.remove_if([](WorldObject* obj) { return obj->GetEntry() != NPC_SANCTUM_SENTRY; });
+ }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetUlduarAI<npc_feral_defenderAI>(creature);
- }
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auriaya_strenght_of_the_pack::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY);
+ }
};
-class SanctumSentryCheck
+// 64392, 64679 - Sentinel Blast
+class spell_auriaya_sentinel_blast : public SpellScript
{
- public:
- bool operator()(WorldObject* object) const
- {
- if (object->GetEntry() == NPC_SANCTUM_SENTRY)
- return false;
-
- return true;
- }
+ PrepareSpellScript(spell_auriaya_sentinel_blast);
+
+ void FilterTargets(std::list<WorldObject*>& unitList)
+ {
+ unitList.remove_if(PlayerOrPetCheck());
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auriaya_sentinel_blast::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auriaya_sentinel_blast::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
};
-class spell_auriaya_strenght_of_the_pack : public SpellScriptLoader
+// 63709 - Aggro Creator
+class spell_auriaya_agro_creator : public SpellScript
{
- public:
- spell_auriaya_strenght_of_the_pack() : SpellScriptLoader("spell_auriaya_strenght_of_the_pack") { }
+ PrepareSpellScript(spell_auriaya_agro_creator);
- class spell_auriaya_strenght_of_the_pack_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_auriaya_strenght_of_the_pack_SpellScript);
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_POUNCE });
+ }
- void FilterTargets(std::list<WorldObject*>& unitList)
- {
- unitList.remove_if(SanctumSentryCheck());
- }
+ void HandleDummyEffect(SpellEffIndex /*effIndex*/)
+ {
+ Creature* caster = GetCaster()->ToCreature();
+ if (!caster || !caster->IsAIEnabled || caster->HasReactState(REACT_PASSIVE))
+ return;
- void Register() override
- {
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auriaya_strenght_of_the_pack_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY);
- }
- };
-
- SpellScript* GetSpellScript() const override
+ if (Unit* target = caster->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, CatsTargetSelector(caster, 5.0f, 10.0f)))
{
- return new spell_auriaya_strenght_of_the_pack_SpellScript();
+ caster->CastSpell(target, SPELL_POUNCE, true);
+ caster->GetThreatManager().AddThreat(target, 50000000.0f, nullptr, true);
+ caster->AI()->AttackStart(target);
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_auriaya_agro_creator::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
-class spell_auriaya_sentinel_blast : public SpellScriptLoader
+// 61906 - Random Aggro Periodic (5 sec)
+class spell_auriaya_random_agro_periodic : public AuraScript
{
- public:
- spell_auriaya_sentinel_blast() : SpellScriptLoader("spell_auriaya_sentinel_blast") { }
+ PrepareAuraScript(spell_auriaya_random_agro_periodic);
- class spell_auriaya_sentinel_blast_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_auriaya_sentinel_blast_SpellScript);
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_FERAL_POUNCE });
+ }
- void FilterTargets(std::list<WorldObject*>& unitList)
- {
- unitList.remove_if(PlayerOrPetCheck());
- }
-
- void Register() override
- {
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auriaya_sentinel_blast_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auriaya_sentinel_blast_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY);
- }
- };
+ void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
+ {
+ Creature* owner = GetUnitOwner()->ToCreature();
+ if (!owner || !owner->IsAIEnabled || owner->HasReactState(REACT_PASSIVE))
+ return;
- SpellScript* GetSpellScript() const override
+ if (Unit* target = owner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, CatsTargetSelector(owner, 15.0f, 25.0f)))
{
- return new spell_auriaya_sentinel_blast_SpellScript();
+ owner->GetThreatManager().AddThreat(target, 3000000.0f, nullptr, true);
+ owner->CastSpell(target, SPELL_FERAL_POUNCE, true);
+ owner->AI()->AttackStart(target);
}
+ else if (Unit* target = owner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0))
+ {
+ owner->GetThreatManager().AddThreat(target, 3000000.0f);
+ owner->AI()->AttackStart(target);
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_auriaya_random_agro_periodic::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
};
+// 64456 - Feral Essence Application Removal
+class spell_auriaya_feral_essence_removal : public SpellScript
+{
+ PrepareSpellScript(spell_auriaya_feral_essence_removal);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_FERAL_ESSENCE });
+ }
+
+ void HandleScriptEffect(SpellEffIndex /*effIndex*/)
+ {
+ if (Aura* essence = GetCaster()->GetAura(SPELL_FERAL_ESSENCE))
+ essence->ModStackAmount(-1);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_auriaya_feral_essence_removal::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+};
+
+// 64496, 64674 - Feral Rush
+class spell_auriaya_feral_rush : public SpellScript
+{
+ PrepareSpellScript(spell_auriaya_feral_rush);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_FERAL_RUSH_2 });
+ }
+
+ void HandleOnHit(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->CastSpell(GetCaster(), SPELL_FERAL_RUSH_2, true);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_auriaya_feral_rush::HandleOnHit, EFFECT_1, SPELL_EFFECT_SCHOOL_DAMAGE);
+ }
+};
class achievement_nine_lives : public AchievementCriteriaScript
{
public:
- achievement_nine_lives() : AchievementCriteriaScript("achievement_nine_lives")
- {
- }
+ achievement_nine_lives() : AchievementCriteriaScript("achievement_nine_lives") { }
bool OnCheck(Player* /*player*/, Unit* target) override
{
if (!target)
return false;
- if (Creature* Auriaya = target->ToCreature())
- if (Auriaya->AI()->GetData(DATA_NINE_LIVES))
+ if (Creature* auriaya = target->ToCreature())
+ if (auriaya->AI()->GetData(DATA_NINE_LIVES))
return true;
return false;
@@ -576,17 +666,15 @@ class achievement_nine_lives : public AchievementCriteriaScript
class achievement_crazy_cat_lady : public AchievementCriteriaScript
{
public:
- achievement_crazy_cat_lady() : AchievementCriteriaScript("achievement_crazy_cat_lady")
- {
- }
+ achievement_crazy_cat_lady() : AchievementCriteriaScript("achievement_crazy_cat_lady") { }
bool OnCheck(Player* /*player*/, Unit* target) override
{
if (!target)
return false;
- if (Creature* Auriaya = target->ToCreature())
- if (Auriaya->AI()->GetData(DATA_CRAZY_CAT_LADY))
+ if (Creature* auriaya = target->ToCreature())
+ if (auriaya->AI()->GetData(DATA_CRAZY_CAT_LADY))
return true;
return false;
@@ -595,12 +683,17 @@ class achievement_crazy_cat_lady : public AchievementCriteriaScript
void AddSC_boss_auriaya()
{
- new boss_auriaya();
- new npc_auriaya_seeping_trigger();
- new npc_feral_defender();
- new npc_sanctum_sentry();
- new spell_auriaya_strenght_of_the_pack();
- new spell_auriaya_sentinel_blast();
+ RegisterUlduarCreatureAI(boss_auriaya);
+ RegisterUlduarCreatureAI(npc_feral_defender);
+ RegisterUlduarCreatureAI(npc_sanctum_sentry);
+ RegisterUlduarCreatureAI(npc_swarming_guardian);
+ RegisterUlduarCreatureAI(npc_seeping_essence_stalker);
+ RegisterSpellScript(spell_auriaya_strenght_of_the_pack);
+ RegisterSpellScript(spell_auriaya_sentinel_blast);
+ RegisterSpellScript(spell_auriaya_agro_creator);
+ RegisterAuraScript(spell_auriaya_random_agro_periodic);
+ RegisterSpellScript(spell_auriaya_feral_essence_removal);
+ RegisterSpellScript(spell_auriaya_feral_rush);
new achievement_nine_lives();
new achievement_crazy_cat_lady();
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
index dac2a8707d9..3925fd3b042 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
@@ -973,9 +973,9 @@ class npc_mimirons_inferno : public CreatureScript
public:
npc_mimirons_inferno() : CreatureScript("npc_mimirons_inferno") { }
- struct npc_mimirons_infernoAI : public npc_escortAI
+ struct npc_mimirons_infernoAI : public EscortAI
{
- npc_mimirons_infernoAI(Creature* creature) : npc_escortAI(creature)
+ npc_mimirons_infernoAI(Creature* creature) : EscortAI(creature)
{
Initialize();
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
@@ -988,11 +988,6 @@ public:
infernoTimer = 2000;
}
- void WaypointReached(uint32 /*waypointId*/) override
- {
-
- }
-
void Reset() override
{
Initialize();
@@ -1002,7 +997,7 @@ public:
void UpdateAI(uint32 diff) override
{
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (!HasEscortState(STATE_ESCORT_ESCORTING))
Start(false, true, ObjectGuid::Empty, nullptr, false, true);
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp
index fe0539fc407..8b5039b8326 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp
@@ -610,7 +610,7 @@ class boss_freya : public CreatureScript
/* 25N */ {62955, 62956, 62957, 62958}
};
- me->CastSpell((Unit*)nullptr, summonSpell[me->GetMap()->GetDifficulty()][elderCount], true);
+ me->CastSpell(nullptr, summonSpell[me->GetMap()->GetDifficulty()][elderCount], true);
Talk(SAY_DEATH);
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
index 3b95b36c375..8200ea8ca06 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
@@ -2129,7 +2129,7 @@ class spell_mimiron_proximity_trigger : public SpellScriptLoader
void HandleDummy(SpellEffIndex /*effIndex*/)
{
- GetCaster()->CastSpell((Unit*)nullptr, SPELL_PROXIMITY_MINE_EXPLOSION, true);
+ GetCaster()->CastSpell(nullptr, SPELL_PROXIMITY_MINE_EXPLOSION, true);
}
void Register() override
@@ -2215,7 +2215,7 @@ class spell_mimiron_rocket_strike : public SpellScriptLoader
void HandleDummy(SpellEffIndex /*effIndex*/)
{
- GetHitUnit()->CastSpell((Unit*)nullptr, SPELL_SCRIPT_EFFECT_ROCKET_STRIKE, true, nullptr, nullptr, GetCaster()->GetGUID());
+ GetHitUnit()->CastSpell(nullptr, SPELL_SCRIPT_EFFECT_ROCKET_STRIKE, true, nullptr, nullptr, GetCaster()->GetGUID());
}
void Register() override
@@ -2262,7 +2262,7 @@ class spell_mimiron_rocket_strike_damage : public SpellScriptLoader
void HandleFriendlyFire(SpellEffIndex /*effIndex*/)
{
- GetHitUnit()->CastSpell((Unit*)nullptr, SPELL_NOT_SO_FRIENDLY_FIRE, true);
+ GetHitUnit()->CastSpell(nullptr, SPELL_NOT_SO_FRIENDLY_FIRE, true);
}
void Register() override
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
index d571bd541df..41985059aae 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
@@ -15,15 +15,15 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/// @todo Harpoon chain from 62505 should not get removed when other chain is applied
-
#include "ScriptMgr.h"
#include "GameObject.h"
#include "GameObjectAI.h"
#include "InstanceScript.h"
#include "Map.h"
#include "MotionMaster.h"
+#include "MoveSplineInit.h"
#include "ObjectAccessor.h"
+#include "PassiveAI.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
@@ -31,1133 +31,1673 @@
#include "SpellScript.h"
#include "TemporarySummon.h"
#include "ulduar.h"
+#include <G3D/Vector3.h>
enum Says
{
// Expedition Commander
- SAY_INTRO = 0,
- SAY_GROUND_PHASE = 1,
- SAY_AGGRO_2 = 2,
+ SAY_COMMANDER_AGGRO = 0,
+ SAY_COMMANDER_GROUND_PHASE = 1,
+ SAY_COMMANDER_ENGINEERS_DEAD = 2,
// Expedition Engineer
- SAY_AGGRO_1 = 0,
- SAY_AGGRO_3 = 1,
- SAY_TURRETS = 2, // unused
+ SAY_AGGRO = 0,
+ SAY_START_REPAIR = 1,
+ SAY_REBUILD_TURRETS = 2,
// Razorscale Controller
- EMOTE_HARPOON = 0,
+ EMOTE_HARPOON = 0,
// Razorscale
- EMOTE_PERMA = 0,
- EMOTE_BREATH = 1
+ EMOTE_PERMA_GROUND = 0,
+ EMOTE_BREATH = 1,
+ EMOTE_BERSERK = 2
};
enum Spells
{
- SPELL_FLAMEBUFFET = 64016,
- SPELL_FIREBALL = 62796,
- SPELL_FLAME_GROUND = 64734,
- SPELL_WINGBUFFET = 62666,
- SPELL_FLAMEBREATH = 63317,
- SPELL_FUSEARMOR = 64771,
- SPELL_FLAMED = 62696,
- SPELL_STUN = 9032,
- SPELL_BERSERK = 47008,
- // Additonal Spells
- // Devouring Flame Spells
- SPELL_DEVOURING_FLAME = 63308,
- SPELL_DEVOURING_FLAME_DAMAGE = 64704,
- SPELL_DEVOURING_FLAME_TRIGGER = 64709,
- // HarpoonSpells
- SPELL_HARPOON_TRIGGER = 62505,
- SPELL_HARPOON_SHOT_1 = 63658,
- SPELL_HARPOON_SHOT_2 = 63657,
- SPELL_HARPOON_SHOT_3 = 63659,
- SPELL_HARPOON_SHOT_4 = 63524,
- // MoleMachine Spells
- SPELL_SUMMON_MOLE_MACHINE = 62899,
- SPELL_SUMMON_IRON_DWARVES = 63116,
- SPELL_SUMMON_IRON_DWARVES_2 = 63114,
- SPELL_SUMMON_IRON_DWARVE_GUARDIAN = 62926,
- SPELL_SUMMON_IRON_DWARVE_WATCHER = 63135,
+ SPELL_FIREBALL = 63815,
+ SPELL_DEVOURING_FLAME = 63236,
+ SPELL_WING_BUFFET = 62666,
+ SPELL_FIREBOLT = 62669,
+ SPELL_FUSE_ARMOR = 64821,
+ SPELL_FUSED_ARMOR = 64774,
+ SPELL_STUN_SELF = 62794,
+ SPELL_BERSERK = 47008,
+
+ // Razorscale Harpoon Fire State
+ SPELL_HARPOON_FIRE_STATE = 62696,
+
+ // Harpoon
+ SPELL_HARPOON_TRIGGER = 62505,
+ SPELL_HARPOON_SHOT_1 = 63658,
+ SPELL_HARPOON_SHOT_2 = 63657,
+ SPELL_HARPOON_SHOT_3 = 63659,
+ SPELL_HARPOON_SHOT_4 = 63524,
+
+ // Razorscale Spawner
+ SPELL_SUMMON_MOLE_MACHINE = 62899,
+ SPELL_SUMMON_IRON_DWARF_GUARDIAN = 62926,
+ SPELL_TRIGGER_SUMMON_IRON_DWARVES = 63968,
+ SPELL_TRIGGER_SUMMON_IRON_DWARVES_2 = 63970,
+ SPELL_TRIGGER_SUMMON_IRON_DWARVES_3 = 63969,
+ SPELL_TRIGGER_SUMMON_IRON_VRYKUL = 63798,
+ SPELL_SUMMON_IRON_DWARF_WATCHER = 63135,
+
+ // Dark Rune Guardian
+ SPELL_STORMSTRIKE = 64757,
+
+ // Dark Rune Sentinel
+ SPELL_BATTLE_SHOUT = 46763,
+ SPELL_HEROIC_STRIKE = 45026,
+ SPELL_WHIRLWIND = 63808,
+
+ // Expedition Defender
+ SPELL_THREAT = 65146,
+
+ // Expedition Trapper
+ SPELL_SHACKLE = 62646
};
-enum NPC
+#define DEVOURING_FLAME_GROUND RAID_MODE<uint32>(64709, 64734)
+#define FLAME_BREATH RAID_MODE<uint32>(63317, 64021)
+#define CHAIN_LIGHTNING RAID_MODE<uint32>(64758, 64759)
+#define LIGHTNING_BOLT RAID_MODE<uint32>(63809, 64696)
+
+enum Actions
{
- NPC_DARK_RUNE_GUARDIAN = 33388,
- NPC_DARK_RUNE_SENTINEL = 33846,
- NPC_DARK_RUNE_WATCHER = 33453,
- MOLE_MACHINE_TRIGGER = 33245,
- NPC_COMMANDER = 33210,
- NPC_ENGINEER = 33287,
- NPC_DEFENDER = 33816,
+ ACTION_START_FIGHT = 1,
+ ACTION_FIX_HARPOONS,
+ ACTION_GROUND_PHASE,
+ ACTION_ENGINEER_DEAD,
+ ACTION_SHACKLE_RAZORSCALE,
+ ACTION_START_PERMA_GROUND,
+ ACTION_RETURN_TO_BASE,
+ ACTION_BUILD_HARPOON_1,
+ ACTION_BUILD_HARPOON_2,
+ ACTION_BUILD_HARPOON_3,
+ ACTION_BUILD_HARPOON_4,
+ ACTION_DESTROY_HARPOONS,
+ ACTION_STOP_CONTROLLERS,
+ ACTION_STOP_CAST
};
-enum DarkRuneSpells
+enum Events
{
+ EVENT_BERSERK = 1,
+ EVENT_FIREBALL,
+ EVENT_DEVOURING_FLAME,
+ EVENT_SUMMON_MINIONS,
+ EVENT_SUMMON_MINIONS_2,
+ EVENT_FLAME_BREATH,
+ EVENT_FLAME_BREATH_GROUND,
+ EVENT_WING_BUFFET,
+ EVENT_RESUME_AIR_PHASE,
+ EVENT_FIREBOLT,
+ EVENT_FUSE_ARMOR,
+ EVENT_RESUME_MOVE_CHASE,
+
+ // Expedition Commander
+ EVENT_BUILD_HARPOON_1,
+ EVENT_BUILD_HARPOON_2,
+ EVENT_BUILD_HARPOON_3,
+ EVENT_BUILD_HARPOON_4,
+ EVENT_HANDLE_DESTROY_HARPOON,
+
+ // Dark Rune Sentinel
+ EVENT_START_COMBAT,
+ EVENT_HEROIC_STRIKE,
+ EVENT_BATTLE_SHOUT,
+ EVENT_WHIRLWIND,
+
// Dark Rune Watcher
- SPELL_CHAIN_LIGHTNING = 64758,
- SPELL_LIGHTNING_BOLT = 63809,
+ EVENT_LIGHTNING_BOLT,
+ EVENT_CHAIN_LIGHTNING,
+
// Dark Rune Guardian
- SPELL_STORMSTRIKE = 64757,
- // Dark Rune Sentinel
- SPELL_BATTLE_SHOUT = 46763,
- SPELL_HEROIC_STRIKE = 45026,
- SPELL_WHIRLWIND = 63807,
+ EVENT_STORMSTRIKE
};
-enum Actions
+enum Misc
{
- ACTION_EVENT_START = 1,
- ACTION_GROUND_PHASE = 2,
- ACTION_HARPOON_BUILD = 3,
- ACTION_PLACE_BROKEN_HARPOON = 4,
- ACTION_COMMANDER_RESET = 7,
+ DATA_QUICK_SHAVE = 29192921, // 2919, 2921 are achievement IDs
+ DATA_IRON_DWARF_MEDIUM_RARE = 29232924,
+ GOSSIP_START_ENCOUNTER = 0,
+ DATA_EXPEDITION_NUMBER = 1,
+ RAZORSCALE_EXPEDITION_GROUP = 1,
+ RAZORSCALE_FIRE_STATE_10_GROUP = 2,
+ RAZORSCALE_FIRE_STATE_25_GROUP = 3,
+ ENGINEER_NORTH = 0,
+ ENGINEER_EAST = 1,
+ ENGINEER_WEST = 2,
+ HARPOON_1 = 0,
+ HARPOON_2 = 1,
+ HARPOON_3 = 2,
+ HARPOON_4 = 3,
+ WORLD_STATE_RAZORSCALE_MUSIC = 4162
};
-enum Phases
+enum MovePoints
{
- PHASE_PERMAGROUND = 1,
- PHASE_GROUND = 2,
- PHASE_FLIGHT = 3,
+ POINT_DEFENDER_ATTACK = 1,
+ POINT_SHACKLE_RAZORSCALE,
+ POINT_BASE,
+ POINT_HARPOON_1,
+ POINT_HARPOON_1_25,
+ POINT_HARPOON_2,
+ POINT_HARPOON_2_25,
+ POINT_HARPOON_3,
+ POINT_HARPOON_4,
+ POINT_RAZORSCALE_FLIGHT,
+ POINT_RAZORSCALE_TAKEOFF,
+ POINT_RAZORSCALE_FLIGHT_2,
+ POINT_RAZORSCALE_LAND,
+ POINT_RAZORSCALE_GROUND,
+ POINT_START_WAYPOINT
};
-enum Events
+enum EngineersSplineMovements
{
- EVENT_BERSERK = 1,
- EVENT_BREATH = 2,
- EVENT_BUFFET = 3,
- EVENT_FIREBALL = 5,
- EVENT_FLIGHT = 6,
- EVENT_DEVOURING = 7,
- EVENT_FLAME = 8,
- EVENT_LAND = 9,
- EVENT_GROUND = 10,
- EVENT_FUSE = 11,
- EVENT_SUMMON = 12,
- // Razorscale Controller
- EVENT_BUILD_HARPOON_1 = 13,
- EVENT_BUILD_HARPOON_2 = 14,
- EVENT_BUILD_HARPOON_3 = 15,
- EVENT_BUILD_HARPOON_4 = 16,
+ SPLINE_ENGINEER_NORTH_10_HARPOON_1 = 1,
+ SPLINE_ENGINEER_NORTH_10_HARPOON_2 = 2,
+ SPLINE_ENGINEER_NORTH_10_BASE = 3,
+ SPLINE_ENGINEER_NORTH_25_HARPOON_1 = 4,
+ SPLINE_ENGINEER_NORTH_25_HARPOON_2 = 5,
+ SPLINE_ENGINEER_NORTH_25_HARPOON_3 = 6,
+ SPLINE_ENGINEER_NORTH_25_HARPOON_4 = 7,
+ SPLINE_ENGINEER_NORTH_25_BASE = 8,
+ SPLINE_ENGINEER_EAST_10_HARPOON_1 = 9,
+ SPLINE_ENGINEER_EAST_10_HARPOON_2 = 10,
+ SPLINE_ENGINEER_EAST_10_BASE = 11,
+ SPLINE_ENGINEER_EAST_25_HARPOON_1 = 12,
+ SPLINE_ENGINEER_EAST_25_HARPOON_2 = 13,
+ SPLINE_ENGINEER_EAST_25_HARPOON_3 = 14,
+ SPLINE_ENGINEER_EAST_25_HARPOON_4 = 15,
+ SPLINE_ENGINEER_WEST_10_HARPOON_1 = 16,
+ SPLINE_ENGINEER_WEST_10_HARPOON_2 = 17,
+ SPLINE_ENGINEER_WEST_10_BASE = 18,
+ SPLINE_ENGINEER_WEST_25_HARPOON_1 = 19,
+ SPLINE_ENGINEER_WEST_25_HARPOON_2 = 20,
+ SPLINE_ENGINEER_WEST_25_HARPOON_3 = 21,
+ SPLINE_ENGINEER_WEST_25_HARPOON_4 = 22,
+ SPLINE_ENGINEER_WEST_25_BASE = 23
};
-#define GROUND_Z 391.517f
-#define GOSSIP_ITEM_1 "Activate Harpoons!"
-
-enum Misc
+enum RazorscalePhases
{
- DATA_QUICK_SHAVE = 29192921, // 2919, 2921 are achievement IDs
- DATA_IRON_DWARF_MEDIUM_RARE = 29232924
+ PHASE_NONE = 0,
+ PHASE_COMBAT,
+ PHASE_GROUND,
+ PHASE_AIR,
+ PHASE_PERMA_GROUND
};
-const Position PosEngRepair[4] =
+Position const PosBrokenHarpoon[4] =
{
- { 590.442f, -130.550f, GROUND_Z, 4.789f },
- { 574.850f, -133.687f, GROUND_Z, 4.252f },
- { 606.567f, -143.369f, GROUND_Z, 4.434f },
- { 560.609f, -142.967f, GROUND_Z, 5.074f },
+ { 571.9465f, -136.0118f, 391.5171f, 2.286379f }, // 1
+ { 589.9233f, -133.6223f, 391.8968f, 3.298687f }, // 2
+ { 559.1199f, -140.5058f, 391.1803f, 4.049168f }, // 0
+ { 606.2297f, -136.7212f, 391.1803f, 5.131269f } // 3
};
-const Position PosDefSpawn[4] =
+Position const PosHarpoon[4] =
{
- { 600.75f, -104.850f, GROUND_Z, 0 },
- { 596.38f, -110.262f, GROUND_Z, 0 },
- { 566.47f, -103.633f, GROUND_Z, 0 },
- { 570.41f, -108.791f, GROUND_Z, 0 },
+ { 571.9012f, -136.5541f, 391.5171f, 4.921829f }, // GO_RAZOR_HARPOON_1
+ { 589.9233f, -133.6223f, 391.8968f, 4.81711f }, // GO_RAZOR_HARPOON_2
+ { 559.1199f, -140.5058f, 391.1803f, 5.061456f }, // GO_RAZOR_HARPOON_3
+ { 606.2297f, -136.7212f, 391.1803f, 4.537859f } // GO_RAZOR_HARPOON_4
};
-const Position PosDefCombat[4] =
+Position const DefendersPosition[6] =
{
- { 614.975f, -155.138f, GROUND_Z, 4.154f },
- { 609.814f, -204.968f, GROUND_Z, 5.385f },
- { 563.531f, -201.557f, GROUND_Z, 4.108f },
- { 560.231f, -153.677f, GROUND_Z, 5.403f },
+ { 624.3065f, -154.4163f, 391.6442f },
+ { 611.6274f, -170.9375f, 391.8087f },
+ { 572.1548f, -167.4471f, 391.8087f },
+ { 558.4640f, -165.0114f, 391.8087f },
+ { 603.3345f, -164.4297f, 391.8087f },
+ { 549.1727f, -159.1180f, 391.8087f }
};
-const Position PosHarpoon[4] =
+Position const TrapperPosition[3] =
{
- { 571.901f, -136.554f, GROUND_Z, 0 },
- { 589.450f, -134.888f, GROUND_Z, 0 },
- { 559.119f, -140.505f, GROUND_Z, 0 },
- { 606.229f, -136.721f, GROUND_Z, 0 },
+ { 574.9293f, -184.5150f, 391.8921f },
+ { 539.7838f, -178.5337f, 391.3053f },
+ { 627.1754f, -177.9638f, 391.5553f }
};
-const Position RazorFlight = { 588.050f, -251.191f, 470.536f, 1.498f };
-const Position RazorGround = { 586.966f, -175.534f, GROUND_Z, 4.682f };
-const Position PosEngSpawn = { 591.951f, -95.9680f, GROUND_Z, 0.000f };
-
-class boss_razorscale_controller : public CreatureScript
+uint32 const SummonMinionsSpells[4] =
{
- public:
- boss_razorscale_controller() : CreatureScript("boss_razorscale_controller") { }
-
- struct boss_razorscale_controllerAI : public ScriptedAI
- {
- boss_razorscale_controllerAI(Creature* creature) : ScriptedAI(creature), summons(me)
- {
- instance = creature->GetInstanceScript();
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
- }
-
- InstanceScript* instance;
- EventMap events;
- SummonList summons;
+ SPELL_TRIGGER_SUMMON_IRON_DWARVES,
+ SPELL_TRIGGER_SUMMON_IRON_DWARVES_2,
+ SPELL_TRIGGER_SUMMON_IRON_DWARVES_3,
+ SPELL_TRIGGER_SUMMON_IRON_VRYKUL
+};
- void Reset() override
- {
- events.Reset();
- summons.DespawnAll();
- me->SetReactState(REACT_PASSIVE);
- }
+uint32 const pathSize = 11;
+G3D::Vector3 const RazorscalePath[pathSize] =
+{
+ { 657.0227f, -361.1278f, 519.5406f },
+ { 698.9319f, -340.9654f, 520.4857f },
+ { 713.8673f, -290.2219f, 518.4573f },
+ { 711.1782f, -259.6798f, 524.6802f },
+ { 695.5101f, -234.6734f, 529.1528f },
+ { 666.9619f, -220.7599f, 531.4860f },
+ { 629.2765f, -219.7951f, 528.9301f },
+ { 597.4018f, -233.7745f, 526.6508f },
+ { 577.5307f, -275.4489f, 528.1241f },
+ { 583.1092f, -319.5873f, 527.9302f },
+ { 611.5800f, -353.1930f, 526.2653f }
+};
- void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
- {
- switch (spell->Id)
- {
- case SPELL_FLAMED:
- if (GameObject* harpoon = instance->GetGameObject(GO_RAZOR_HARPOON_1))
- harpoon->RemoveFromWorld();
- if (GameObject* harpoon = instance->GetGameObject(GO_RAZOR_HARPOON_2))
- harpoon->RemoveFromWorld();
- if (GameObject* harpoon = instance->GetGameObject(GO_RAZOR_HARPOON_3))
- harpoon->RemoveFromWorld();
- if (GameObject* harpoon = instance->GetGameObject(GO_RAZOR_HARPOON_4))
- harpoon->RemoveFromWorld();
- DoAction(ACTION_HARPOON_BUILD);
- DoAction(ACTION_PLACE_BROKEN_HARPOON);
- break;
- case SPELL_HARPOON_SHOT_1:
- case SPELL_HARPOON_SHOT_2:
- case SPELL_HARPOON_SHOT_3:
- case SPELL_HARPOON_SHOT_4:
- DoCast(SPELL_HARPOON_TRIGGER);
- break;
- }
- }
+Position const RazorFlightPosition = { 585.3610f, -173.5592f, 456.8430f, 1.526665f };
+Position const RazorFlightPositionPhase2 = { 619.1450f, -238.0780f, 475.1800f, 1.423917f };
+Position const RazorscaleLand = { 585.4010f, -173.5430f, 408.5080f, 1.570796f };
+Position const RazorscaleGroundPosition = { 585.4010f, -173.5430f, 391.6421f, 1.570796f };
+Position const RazorscaleFirstPoint = { 657.0227f, -361.1278f, 519.5406f };
- void JustDied(Unit* /*killer*/) override
+struct boss_razorscale : public BossAI
+{
+ boss_razorscale(Creature* creature) : BossAI(creature, BOSS_RAZORSCALE)
+ {
+ Initialize();
+ }
+
+ void Initialize()
+ {
+ _engineersCount = 3;
+ _defendersCount = 0;
+ _engineersSummonCount = 0;
+ _harpoonHitCount = 0;
+ _trappersCount = 0;
+ _permaGround = false;
+ _flyCount = 0;
+ me->SetDisableGravity(true);
+ me->SetByteFlag(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
+ }
+
+ void Reset() override
+ {
+ _Reset();
+ Initialize();
+ events.SetPhase(PHASE_NONE);
+ me->SummonCreatureGroup(RAZORSCALE_EXPEDITION_GROUP);
+ me->SummonCreatureGroup(RAZORSCALE_FIRE_STATE_10_GROUP);
+ if (Is25ManRaid())
+ me->SummonCreatureGroup(RAZORSCALE_FIRE_STATE_25_GROUP);
+ // @Developer remove this comment when someone create a way to change view distance for objects
+ // me->GetMotionMaster()->MovePoint(POINT_START_WAYPOINT, RazorscaleFirstPoint);
+ // And apply it on DB: UPDATE `creature` SET `position_x`=699.7847, `position_y`=-424.8246, `position_z`=589.2745, `orientation`=1.972222 WHERE `guid`=137611; -- Razorscale
+ SetCombatMovement(false);
+ }
+
+ void HandleInitialMovement()
+ {
+ Movement::PointsArray path(RazorscalePath, RazorscalePath + pathSize);
+ Movement::MoveSplineInit init(me);
+ init.MovebyPath(path, 0);
+ init.SetCyclic();
+ init.SetFly();
+ init.Launch();
+ }
+
+ bool CanAIAttack(Unit const* target) const override
+ {
+ switch (target->GetEntry())
+ {
+ case NPC_EXPEDITION_DEFENDER:
+ case NPC_EXPEDITION_TRAPPER:
+ case NPC_EXPEDITION_COMMANDER:
+ case NPC_EXPEDITION_ENGINEER:
+ return false;
+ default:
+ return BossAI::CanAIAttack(target);
+ }
+ }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _EnterCombat();
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
+ ScheduleAirPhaseEvents();
+ summons.DoAction(ACTION_START_FIGHT, DummyEntryCheckPredicate());
+ events.ScheduleEvent(EVENT_BERSERK, Minutes(15));
+ HandleMusic(true);
+ me->SetByteFlag(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
+ }
+
+ void ScheduleAirPhaseEvents()
+ {
+ events.ScheduleEvent(EVENT_FIREBALL, Seconds(3), 0, PHASE_AIR);
+ events.ScheduleEvent(EVENT_DEVOURING_FLAME, Seconds(9), 0, PHASE_AIR);
+ events.ScheduleEvent(EVENT_SUMMON_MINIONS, Seconds(1), 0, PHASE_AIR);
+ }
+
+ void ScheduleGroundPhaseEvents()
+ {
+ events.ScheduleEvent(EVENT_FIREBOLT, Seconds(3), 0, PHASE_PERMA_GROUND);
+ events.ScheduleEvent(EVENT_FUSE_ARMOR, Seconds(15), 0, PHASE_PERMA_GROUND);
+ events.ScheduleEvent(EVENT_FLAME_BREATH_GROUND, Seconds(18), 0, PHASE_PERMA_GROUND);
+ events.ScheduleEvent(EVENT_DEVOURING_FLAME, Seconds(22), 0, PHASE_PERMA_GROUND);
+ }
+
+ void DoAction(int32 actionId) override
+ {
+ switch (actionId)
+ {
+ case ACTION_START_FIGHT:
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
+ me->SetSpeedRate(MOVE_RUN, 3.0f);
+ me->StopMoving();
+ me->GetMotionMaster()->MovePoint(POINT_RAZORSCALE_FLIGHT, RazorFlightPosition);
+ break;
+ case ACTION_GROUND_PHASE:
+ me->InterruptNonMeleeSpells(false);
+ events.SetPhase(PHASE_GROUND);
+ _harpoonHitCount = 0;
+ me->SetSpeedRate(MOVE_RUN, 3.0f);
+ me->GetMotionMaster()->MovePoint(POINT_RAZORSCALE_LAND, RazorscaleLand);
+ break;
+ case ACTION_START_PERMA_GROUND:
{
- events.Reset();
- summons.DespawnAll();
+ me->SetDisableGravity(false);
+ me->RemoveByteFlag(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
+ me->RemoveAurasDueToSpell(SPELL_STUN_SELF);
+ Talk(EMOTE_PERMA_GROUND);
+ DoCastSelf(SPELL_WING_BUFFET);
+ EntryCheckPredicate pred(NPC_EXPEDITION_TRAPPER);
+ summons.DoAction(ACTION_STOP_CAST, pred);
+ events.ScheduleEvent(EVENT_RESUME_MOVE_CHASE, Milliseconds(1));
+ ScheduleGroundPhaseEvents();
+ break;
}
+ default:
+ break;
+ }
+ }
- void DoAction(int32 action) override
- {
- if (instance->GetBossState(BOSS_RAZORSCALE) != IN_PROGRESS)
- return;
+ void MovementInform(uint32 type, uint32 pointId) override
+ {
+ if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE)
+ return;
- switch (action)
+ switch (pointId)
+ {
+ case POINT_START_WAYPOINT:
+ HandleInitialMovement();
+ break;
+ case POINT_RAZORSCALE_FLIGHT:
+ me->UpdateSpeed(MOVE_RUN);
+ me->SetFacingTo(RazorFlightPosition.GetOrientation());
+ DoZoneInCombat();
+ break;
+ case POINT_RAZORSCALE_GROUND:
+ me->SetDisableGravity(false);
+ me->RemoveByteFlag(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
+ if (!_permaGround)
{
- case ACTION_HARPOON_BUILD:
- events.ScheduleEvent(EVENT_BUILD_HARPOON_1, 50000);
- if (me->GetMap()->GetSpawnMode() == RAID_DIFFICULTY_25MAN_NORMAL)
- events.ScheduleEvent(EVENT_BUILD_HARPOON_3, 90000);
- break;
- case ACTION_PLACE_BROKEN_HARPOON:
- for (uint8 n = 0; n < RAID_MODE(2, 4); n++)
- me->SummonGameObject(GO_RAZOR_BROKEN_HARPOON, PosHarpoon[n].GetPositionX(), PosHarpoon[n].GetPositionY(), PosHarpoon[n].GetPositionZ(), 2.286f, QuaternionData(), 180);
- break;
+ DoCastSelf(SPELL_STUN_SELF, true);
+ EntryCheckPredicate pred(NPC_EXPEDITION_TRAPPER);
+ summons.DoAction(ACTION_SHACKLE_RAZORSCALE, pred);
+ if (Creature* commander = instance->GetCreature(DATA_EXPEDITION_COMMANDER))
+ commander->AI()->DoAction(ACTION_GROUND_PHASE);
+ events.ScheduleEvent(EVENT_FLAME_BREATH, Seconds(30), 0, PHASE_GROUND);
}
- }
+ break;
+ case POINT_RAZORSCALE_TAKEOFF:
+ me->SetSpeedRate(MOVE_RUN, 3.0f);
+ me->GetMotionMaster()->MovePoint(POINT_RAZORSCALE_FLIGHT_2, RazorFlightPositionPhase2);
+ break;
+ case POINT_RAZORSCALE_FLIGHT_2:
+ me->SetFacingTo(RazorFlightPositionPhase2.GetOrientation());
+ me->SetReactState(REACT_AGGRESSIVE);
+ ScheduleAirPhaseEvents();
+ ++_flyCount;
+ me->UpdateSpeed(MOVE_RUN);
+ break;
+ case POINT_RAZORSCALE_LAND:
+ me->UpdateSpeed(MOVE_RUN);
+ me->SetFacingTo(RazorscaleLand.GetOrientation());
+ me->GetMotionMaster()->MoveLand(POINT_RAZORSCALE_GROUND, RazorscaleGroundPosition);
+ break;
+ default:
+ break;
+ }
+ }
- void UpdateAI(uint32 Diff) override
- {
- events.Update(Diff);
+ void JustSummoned(Creature* summon) override
+ {
+ BossAI::JustSummoned(summon);
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_BUILD_HARPOON_1:
- Talk(EMOTE_HARPOON);
- if (GameObject* harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_1, PosHarpoon[0].GetPositionX(), PosHarpoon[0].GetPositionY(), PosHarpoon[0].GetPositionZ(), 4.790f, QuaternionData(), uint32(me->GetRespawnTime())))
- {
- if (GameObject* brokenHarpoon = harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f)) //only nearest broken harpoon
- brokenHarpoon->RemoveFromWorld();
- events.ScheduleEvent(EVENT_BUILD_HARPOON_2, 20000);
- events.CancelEvent(EVENT_BUILD_HARPOON_1);
- }
- return;
- case EVENT_BUILD_HARPOON_2:
- Talk(EMOTE_HARPOON);
- if (GameObject* harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_2, PosHarpoon[1].GetPositionX(), PosHarpoon[1].GetPositionY(), PosHarpoon[1].GetPositionZ(), 4.659f, QuaternionData(), uint32(me->GetRespawnTime())))
- {
- if (GameObject* brokenHarpoon = harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f))
- brokenHarpoon->RemoveFromWorld();
- events.CancelEvent(EVENT_BUILD_HARPOON_2);
- }
- return;
- case EVENT_BUILD_HARPOON_3:
- Talk(EMOTE_HARPOON);
- if (GameObject* harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_3, PosHarpoon[2].GetPositionX(), PosHarpoon[2].GetPositionY(), PosHarpoon[2].GetPositionZ(), 5.382f, QuaternionData(), uint32(me->GetRespawnTime())))
- {
- if (GameObject* brokenHarpoon = harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f))
- brokenHarpoon->RemoveFromWorld();
- events.ScheduleEvent(EVENT_BUILD_HARPOON_4, 20000);
- events.CancelEvent(EVENT_BUILD_HARPOON_3);
- }
- return;
- case EVENT_BUILD_HARPOON_4:
- Talk(EMOTE_HARPOON);
- if (GameObject* harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_4, PosHarpoon[3].GetPositionX(), PosHarpoon[3].GetPositionY(), PosHarpoon[3].GetPositionZ(), 4.266f, QuaternionData(), uint32(me->GetRespawnTime())))
- {
- if (GameObject* brokenHarpoon = harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f))
- brokenHarpoon->RemoveFromWorld();
- events.CancelEvent(EVENT_BUILD_HARPOON_4);
- }
- return;
- }
- }
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
+ switch (summon->GetEntry())
{
- return GetUlduarAI<boss_razorscale_controllerAI>(creature);
+ case NPC_EXPEDITION_DEFENDER:
+ summon->AI()->SetData(DATA_EXPEDITION_NUMBER, _defendersCount);
+ ++_defendersCount;
+ break;
+ case NPC_EXPEDITION_ENGINEER:
+ summon->AI()->SetData(DATA_EXPEDITION_NUMBER, _engineersSummonCount);
+ ++_engineersSummonCount;
+ break;
+ case NPC_EXPEDITION_TRAPPER:
+ summon->AI()->SetData(DATA_EXPEDITION_NUMBER, _trappersCount);
+ ++_trappersCount;
+ break;
+ default:
+ break;
}
-};
+ }
-class go_razorscale_harpoon : public GameObjectScript
-{
- public:
- go_razorscale_harpoon() : GameObjectScript("go_razorscale_harpoon") { }
-
- struct go_razorscale_harpoonAI : public GameObjectAI
+ void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
+ {
+ if (summon->GetEntry() == NPC_EXPEDITION_ENGINEER)
{
- go_razorscale_harpoonAI(GameObject* go) : GameObjectAI(go), instance(go->GetInstanceScript()) { }
-
- InstanceScript* instance;
-
- bool GossipHello(Player* /*player*/) override
- {
- if (instance->GetCreature(BOSS_RAZORSCALE))
- me->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
- return false;
- }
- };
+ _engineersCount--;
+ if (_engineersCount == 0)
+ if (Creature* commander = instance->GetCreature(DATA_EXPEDITION_COMMANDER))
+ commander->AI()->DoAction(ACTION_ENGINEER_DEAD);
+ }
+ }
- GameObjectAI* GetAI(GameObject* go) const override
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
+ {
+ if (spell->Id == SPELL_HARPOON_TRIGGER)
{
- return GetUlduarAI<go_razorscale_harpoonAI>(go);
+ _harpoonHitCount++;
+ if (_harpoonHitCount == RAID_MODE(2, 4))
+ DoAction(ACTION_GROUND_PHASE);
}
-};
-
-class boss_razorscale : public CreatureScript
-{
- public:
- boss_razorscale() : CreatureScript("boss_razorscale") { }
-
- struct boss_razorscaleAI : public BossAI
+ }
+
+ uint32 GetData(uint32 type) const override
+ {
+ if (type == DATA_QUICK_SHAVE && _flyCount <= 1)
+ return 1;
+ return 0;
+ }
+
+ void EnterEvadeMode(EvadeReason why) override
+ {
+ if (why == EVADE_REASON_BOUNDARY && !events.IsInPhase(PHASE_PERMA_GROUND))
+ return;
+
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ summons.DespawnAll();
+ HandleMusic(false);
+ _EnterEvadeMode();
+ _DespawnAtEvade();
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ HandleMusic(false);
+ }
+
+ void HandleMusic(bool active)
+ {
+ uint32 enabled = active ? 1 : 0;
+ instance->DoUpdateWorldState(WORLD_STATE_RAZORSCALE_MUSIC, enabled);
+ }
+
+ void SummonMinions()
+ {
+ float x = frand(540.0f, 640.0f); // Safe range is between 500 and 650
+ float y = frand(-230.0f, -195.0f); // Safe range is between -235 and -145
+ float z = 391.517f; // Ground level
+ me->SummonCreature(NPC_RAZORSCALE_SPAWNER, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN, 15000);
+ }
+
+ void DamageTaken(Unit* /*done_by*/, uint32 &damage) override
+ {
+ if (!_permaGround && me->HealthBelowPctDamaged(50, damage) && events.IsInPhase(PHASE_GROUND))
{
- boss_razorscaleAI(Creature* creature) : BossAI(creature, BOSS_RAZORSCALE)
- {
- Initialize();
- // Do not let Razorscale be affected by Battle Shout buff
- me->ApplySpellImmune(0, IMMUNITY_ID, (SPELL_BATTLE_SHOUT), true);
- FlyCount = 0;
- EnrageTimer = 0;
- Enraged = false;
- phase = PHASE_GROUND;
- }
-
- void Initialize()
- {
- PermaGround = false;
- HarpoonCounter = 0;
- }
-
- Phases phase;
-
- uint32 EnrageTimer;
- uint8 FlyCount;
- uint8 HarpoonCounter;
- bool PermaGround;
- bool Enraged;
-
- void Reset() override
- {
- _Reset();
- me->SetCanFly(true);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetReactState(REACT_PASSIVE);
- Initialize();
- if (Creature* commander = instance->GetCreature(DATA_EXPEDITION_COMMANDER))
- commander->AI()->DoAction(ACTION_COMMANDER_RESET);
- }
-
- void EnterCombat(Unit* /*who*/) override
- {
- _EnterCombat();
- if (Creature* controller = instance->GetCreature(DATA_RAZORSCALE_CONTROL))
- controller->AI()->DoAction(ACTION_HARPOON_BUILD);
- me->SetSpeedRate(MOVE_FLIGHT, 3.0f);
- me->SetReactState(REACT_PASSIVE);
- phase = PHASE_GROUND;
- events.SetPhase(PHASE_GROUND);
- FlyCount = 0;
- EnrageTimer = 600000;
- Enraged = false;
- events.ScheduleEvent(EVENT_FLIGHT, 0, 0, PHASE_GROUND);
- }
-
- void JustDied(Unit* /*killer*/) override
- {
- _JustDied();
- if (Creature* controller = instance->GetCreature(DATA_RAZORSCALE_CONTROL))
- controller->AI()->Reset();
- }
+ _permaGround = true;
+ me->SetReactState(REACT_AGGRESSIVE);
+ events.SetPhase(PHASE_PERMA_GROUND);
+ DoAction(ACTION_START_PERMA_GROUND);
+ }
+ }
- void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
- {
- if (spell->Id == SPELL_HARPOON_TRIGGER)
- ++HarpoonCounter;
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- void MovementInform(uint32 type, uint32 id) override
- {
- if (type == EFFECT_MOTION_TYPE && id == 1)
- {
- phase = PHASE_GROUND;
- events.SetPhase(PHASE_GROUND);
- events.ScheduleEvent(EVENT_LAND, 0, 0, PHASE_GROUND);
- }
- }
+ events.Update(diff);
- uint32 GetData(uint32 type) const override
- {
- if (type == DATA_QUICK_SHAVE)
- if (FlyCount <= 2)
- return 1;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- return 0;
- }
-
- void UpdateAI(uint32 Diff) override
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- if (!UpdateVictim())
- return;
-
- events.Update(Diff);
-
- if (HealthBelowPct(50) && !PermaGround)
- EnterPermaGround();
-
- if (EnrageTimer <= Diff && !Enraged)
- {
- DoCast(me, SPELL_BERSERK);
- Enraged = true;
- }
- else
- EnrageTimer -= Diff;
-
- if (HarpoonCounter == RAID_MODE(2, 4))
+ case EVENT_BERSERK:
+ DoCastSelf(SPELL_BERSERK, true);
+ Talk(EMOTE_BERSERK, me);
+ break;
+ case EVENT_FIREBALL:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
+ DoCast(target, SPELL_FIREBALL);
+ events.Repeat(Seconds(2), Seconds(3));
+ break;
+ case EVENT_DEVOURING_FLAME:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
+ DoCast(target, SPELL_DEVOURING_FLAME);
+ if (_permaGround)
+ events.Repeat(Seconds(10), Seconds(12));
+ else
+ events.Repeat(Seconds(6), Seconds(12));
+ break;
+ case EVENT_SUMMON_MINIONS:
{
- HarpoonCounter = 0;
- me->GetMotionMaster()->MoveLand(1, RazorGround);
- }
-
- if (phase == PHASE_GROUND)
- {
- while (uint32 eventId = events.ExecuteEvent())
+ uint8 random = urand(2, 4);
+ uint8 time = 5;
+ for (uint8 n = 0; n < random; ++n)
{
- switch (eventId)
- {
- case EVENT_FLIGHT:
- phase = PHASE_FLIGHT;
- events.SetPhase(PHASE_FLIGHT);
- me->SetCanFly(true);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetReactState(REACT_PASSIVE);
- me->AttackStop();
- me->GetMotionMaster()->MoveTakeoff(0, RazorFlight);
- events.ScheduleEvent(EVENT_FIREBALL, 7000, 0, PHASE_FLIGHT);
- events.ScheduleEvent(EVENT_DEVOURING, 10000, 0, PHASE_FLIGHT);
- events.ScheduleEvent(EVENT_SUMMON, 5000, 0, PHASE_FLIGHT);
- ++FlyCount;
- return;
- case EVENT_LAND:
- me->SetCanFly(false);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED);
- if (Creature* commander = instance->GetCreature(DATA_EXPEDITION_COMMANDER))
- commander->AI()->DoAction(ACTION_GROUND_PHASE);
- events.ScheduleEvent(EVENT_BREATH, 30000, 0, PHASE_GROUND);
- events.ScheduleEvent(EVENT_BUFFET, 33000, 0, PHASE_GROUND);
- events.ScheduleEvent(EVENT_FLIGHT, 35000, 0, PHASE_GROUND);
- return;
- case EVENT_BREATH:
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED);
- me->RemoveAllAuras();
- me->SetReactState(REACT_AGGRESSIVE);
- Talk(EMOTE_BREATH);
- DoCastAOE(SPELL_FLAMEBREATH);
- events.CancelEvent(EVENT_BREATH);
- return;
- case EVENT_BUFFET:
- DoCastAOE(SPELL_WINGBUFFET);
- if (Creature* controller = instance->GetCreature(DATA_RAZORSCALE_CONTROL))
- controller->CastSpell(controller, SPELL_FLAMED, true);
- events.CancelEvent(EVENT_BUFFET);
- return;
- }
+ events.ScheduleEvent(EVENT_SUMMON_MINIONS_2, Seconds(time), 0, PHASE_AIR);
+ time += 5;
}
+ events.Repeat(Seconds(40));
+ break;
}
- if (phase == PHASE_PERMAGROUND)
+ case EVENT_SUMMON_MINIONS_2:
+ SummonMinions();
+ break;
+ case EVENT_FLAME_BREATH:
+ me->RemoveAurasDueToSpell(SPELL_STUN_SELF);
+ Talk(EMOTE_BREATH, me);
+ DoCastVictim(FLAME_BREATH);
+ events.ScheduleEvent(EVENT_WING_BUFFET, Seconds(2), 0, PHASE_GROUND);
+ break;
+ case EVENT_FLAME_BREATH_GROUND:
+ Talk(EMOTE_BREATH, me);
+ DoCastVictim(FLAME_BREATH);
+ events.Repeat(Seconds(15), Seconds(18));
+ break;
+ case EVENT_WING_BUFFET:
{
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_FLAME:
- DoCastAOE(SPELL_FLAMEBUFFET);
- events.ScheduleEvent(EVENT_FLAME, 10000, 0, PHASE_PERMAGROUND);
- return;
- case EVENT_BREATH:
- Talk(EMOTE_BREATH);
- DoCastVictim(SPELL_FLAMEBREATH);
- events.ScheduleEvent(EVENT_BREATH, 20000, 0, PHASE_PERMAGROUND);
- return;
- case EVENT_FIREBALL:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 200.0f, true))
- DoCast(target, SPELL_FIREBALL);
- events.ScheduleEvent(EVENT_FIREBALL, 3000, 0, PHASE_PERMAGROUND);
- return;
- case EVENT_DEVOURING:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 200.0f, true))
- DoCast(target, SPELL_DEVOURING_FLAME);
- events.ScheduleEvent(EVENT_DEVOURING, 10000, 0, PHASE_PERMAGROUND);
- return;
- case EVENT_BUFFET:
- DoCastAOE(SPELL_WINGBUFFET);
- events.CancelEvent(EVENT_BUFFET);
- return;
- case EVENT_FUSE:
- DoCastVictim(SPELL_FUSEARMOR);
- events.ScheduleEvent(EVENT_FUSE, 10000, 0, PHASE_PERMAGROUND);
- return;
- }
- }
-
- DoMeleeAttackIfReady();
+ DoCastSelf(SPELL_WING_BUFFET);
+ events.ScheduleEvent(EVENT_FIREBOLT, Seconds(2), 0, PHASE_GROUND);
+ events.ScheduleEvent(EVENT_RESUME_AIR_PHASE, Seconds(4), 0, PHASE_GROUND);
+ EntryCheckPredicate pred(NPC_EXPEDITION_TRAPPER);
+ summons.DoAction(ACTION_STOP_CAST, pred);
+ break;
}
- else
+ case EVENT_RESUME_AIR_PHASE:
{
- if (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_FIREBALL:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 200.0f, true))
- DoCast(target, SPELL_FIREBALL);
- events.ScheduleEvent(EVENT_FIREBALL, 3000, 0, PHASE_FLIGHT);
- return;
- case EVENT_DEVOURING:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 200.0f, true))
- me->CastSpell(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), SPELL_DEVOURING_FLAME, true);
- events.ScheduleEvent(EVENT_DEVOURING, 10000, 0, PHASE_FLIGHT);
- return;
- case EVENT_SUMMON:
- SummonMoleMachines();
- events.ScheduleEvent(EVENT_SUMMON, 45000, 0, PHASE_FLIGHT);
- return;
- }
- }
+ me->SetDisableGravity(true);
+ me->SetByteFlag(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
+ events.SetPhase(PHASE_AIR);
+ me->SetReactState(REACT_PASSIVE);
+ Position pos = me->GetPosition();
+ pos.m_positionZ += 10.0f;
+ me->GetMotionMaster()->MoveTakeoff(POINT_RAZORSCALE_TAKEOFF, pos);
+ EntryCheckPredicate pred(NPC_EXPEDITION_ENGINEER);
+ summons.DoAction(ACTION_FIX_HARPOONS, pred);
+ break;
}
+ case EVENT_FIREBOLT:
+ DoCastSelf(SPELL_FIREBOLT);
+ break;
+ case EVENT_FUSE_ARMOR:
+ DoCastVictim(SPELL_FUSE_ARMOR);
+ events.Repeat(Seconds(10), Seconds(15));
+ break;
+ case EVENT_RESUME_MOVE_CHASE:
+ SetCombatMovement(true);
+ if (Unit* victim = me->GetVictim())
+ me->GetMotionMaster()->MoveChase(victim);
+ break;
+ default:
+ break;
}
- void EnterPermaGround()
- {
- Talk(EMOTE_PERMA);
- phase = PHASE_PERMAGROUND;
- events.SetPhase(PHASE_PERMAGROUND);
- me->SetCanFly(false);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED);
- me->SetReactState(REACT_AGGRESSIVE);
- me->RemoveAurasDueToSpell(SPELL_HARPOON_TRIGGER);
- me->SetSpeedRate(MOVE_FLIGHT, 1.0f);
- PermaGround = true;
- DoCastAOE(SPELL_FLAMEBREATH);
- events.ScheduleEvent(EVENT_FLAME, 15000, 0, PHASE_PERMAGROUND);
- events.RescheduleEvent(EVENT_DEVOURING, 15000, 0, PHASE_PERMAGROUND);
- events.RescheduleEvent(EVENT_BREATH, 20000, 0, PHASE_PERMAGROUND);
- events.RescheduleEvent(EVENT_FIREBALL, 3000, 0, PHASE_PERMAGROUND);
- events.RescheduleEvent(EVENT_DEVOURING, 6000, 0, PHASE_PERMAGROUND);
- events.RescheduleEvent(EVENT_BUFFET, 2500, 0, PHASE_PERMAGROUND);
- events.RescheduleEvent(EVENT_FUSE, 5000, 0, PHASE_PERMAGROUND);
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
+
+ if (events.IsInPhase(PHASE_PERMA_GROUND))
+ DoMeleeAttackIfReady();
+ }
+
+private:
+ uint8 _engineersCount;
+ uint8 _engineersSummonCount;
+ uint8 _defendersCount;
+ uint8 _harpoonHitCount;
+ uint8 _trappersCount;
+ bool _permaGround;
+ uint32 _flyCount;
+};
- void SummonMoleMachines()
+struct npc_expedition_commander : public ScriptedAI
+{
+ npc_expedition_commander(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()),
+ _is25Man(Is25ManRaid()), _building(false), _destroy(false), _stopControllers(false) { }
+
+ void Reset() override
+ {
+ _events.Reset();
+ _events.SetPhase(PHASE_NONE);
+ BuildBrokenHarpoons();
+ }
+
+ bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
+ {
+ if (gossipListId == GOSSIP_START_ENCOUNTER)
+ {
+ CloseGossipMenuFor(player);
+ _events.SetPhase(PHASE_COMBAT);
+ me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ if (Creature* razorscale = _instance->GetCreature(BOSS_RAZORSCALE))
+ razorscale->AI()->DoAction(ACTION_START_FIGHT);
+ return true;
+ }
+ return false;
+ }
+
+ void BuildBrokenHarpoons()
+ {
+ uint8 harpoonNumber = _is25Man ? 4 : 2;
+ for (uint8 i = 0; i < harpoonNumber; ++i)
+ me->SummonGameObject(GO_RAZOR_BROKEN_HARPOON, PosBrokenHarpoon[i], QuaternionData(0.0f, 0.0f, -0.8987932f, 0.4383728f), WEEK);
+ }
+
+ void DestroyHarpoons()
+ {
+ for (ObjectGuid harpoonGuid : _harpoons)
+ if (GameObject* harpoon = ObjectAccessor::GetGameObject(*me, harpoonGuid))
+ harpoon->RemoveFromWorld();
+
+ _harpoons.clear();
+ BuildBrokenHarpoons();
+ _events.ScheduleEvent(EVENT_HANDLE_DESTROY_HARPOON, Seconds(10));
+ }
+
+ void HandleControllersStopCast()
+ {
+ std::list<Creature*> Controllers;
+ me->GetCreatureListWithEntryInGrid(Controllers, NPC_RAZORSCALE_CONTROLLER, 100.0f);
+
+ for (Creature* controller : Controllers)
+ controller->InterruptNonMeleeSpells(false);
+
+ _stopControllers = false;
+ }
+
+ void BuildHarpoon(uint8 harpoonNumber)
+ {
+
+ if (_is25Man)
+ {
+ switch (harpoonNumber)
{
- // 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(2, 4);
- for (uint8 n = 0; n < random; n++)
- {
- float x = float(irand(540, 640)); // Safe range is between 500 and 650
- float y = float(irand(-230, -195)); // Safe range is between -235 and -145
- float z = GROUND_Z; // Ground level
- me->SummonCreature(MOLE_MACHINE_TRIGGER, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN, 15000);
- }
+ case HARPOON_1:
+ if (GameObject* harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_3, PosHarpoon[2], QuaternionData(0.0f, 0.0f, -0.573576f, 0.8191524f), WEEK))
+ _harpoons.emplace_back(harpoon->GetGUID());
+ break;
+ case HARPOON_2:
+ if (GameObject* harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_1, PosHarpoon[0], QuaternionData(0.0f, 0.0f, -0.6293201f, 0.7771462f), WEEK))
+ _harpoons.emplace_back(harpoon->GetGUID());
+ break;
+ case HARPOON_3:
+ if (GameObject* harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_2, PosHarpoon[1], QuaternionData(0.0f, 0.0f, -0.6691303f, 0.743145f), WEEK))
+ _harpoons.emplace_back(harpoon->GetGUID());
+ break;
+ case HARPOON_4:
+ if (GameObject* harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_4, PosHarpoon[3], QuaternionData(0.0f, 0.0f, -0.7660437f, 0.6427886f), WEEK))
+ _harpoons.emplace_back(harpoon->GetGUID());
+ break;
+ default:
+ break;
}
-
- void DoAction(int32 action) override
+ }
+ else
+ {
+ switch (harpoonNumber)
{
- switch (action)
- {
- case ACTION_EVENT_START:
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
- me->SetReactState(REACT_AGGRESSIVE);
- DoZoneInCombat(me, 150.0f);
- break;
- }
+ case HARPOON_1:
+ if (GameObject* harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_1, PosHarpoon[harpoonNumber], QuaternionData(0.0f, 0.0f, -0.6293201f, 0.7771462f), 0))
+ _harpoons.emplace_back(harpoon->GetGUID());
+ break;
+ case HARPOON_2:
+ if (GameObject* harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_2, PosHarpoon[harpoonNumber], QuaternionData(0.0f, 0.0f, -0.6691303f, 0.743145f), 0))
+ _harpoons.emplace_back(harpoon->GetGUID());
+ break;
+ default:
+ break;
}
- };
+ }
+ }
+
+ void DoAction(int32 actionId) override
+ {
+ if (_building && actionId != ACTION_ENGINEER_DEAD)
+ return;
- CreatureAI* GetAI(Creature* creature) const override
+ switch (actionId)
{
- return GetUlduarAI<boss_razorscaleAI>(creature);
+ case ACTION_START_FIGHT:
+ Talk(SAY_COMMANDER_AGGRO);
+ break;
+ case ACTION_GROUND_PHASE:
+ Talk(SAY_COMMANDER_GROUND_PHASE);
+ break;
+ case ACTION_ENGINEER_DEAD:
+ Talk(SAY_COMMANDER_ENGINEERS_DEAD);
+ _events.Reset();
+ _building = false;
+ break;
+ case ACTION_BUILD_HARPOON_1:
+ _building = true;
+ _events.ScheduleEvent(EVENT_BUILD_HARPOON_1, Seconds(18));
+ break;
+ case ACTION_BUILD_HARPOON_2:
+ _building = true;
+ _events.ScheduleEvent(EVENT_BUILD_HARPOON_2, Seconds(18));
+ break;
+ case ACTION_BUILD_HARPOON_3:
+ _building = true;
+ _events.ScheduleEvent(EVENT_BUILD_HARPOON_3, Seconds(18));
+ break;
+ case ACTION_BUILD_HARPOON_4:
+ _building = true;
+ _events.ScheduleEvent(EVENT_BUILD_HARPOON_4, Seconds(18));
+ break;
+ case ACTION_DESTROY_HARPOONS:
+ if (_destroy)
+ return;
+ _destroy = true;
+ DestroyHarpoons();
+ break;
+ case ACTION_STOP_CONTROLLERS:
+ if (_stopControllers)
+ return;
+ _stopControllers = true;
+ HandleControllersStopCast();
+ break;
+ default:
+ break;
}
-};
+ }
-class npc_expedition_commander : public CreatureScript
-{
- public:
- npc_expedition_commander() : CreatureScript("npc_expedition_commander") { }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!_events.IsInPhase(PHASE_COMBAT))
+ return;
- struct npc_expedition_commanderAI : public ScriptedAI
- {
- npc_expedition_commanderAI(Creature* creature) : ScriptedAI(creature), summons(creature)
- {
- Initialize();
- instance = me->GetInstanceScript();
- }
+ _events.Update(diff);
- void Initialize()
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
{
- AttackStartTimer = 0;
- Phase = 0;
- Greet = false;
+ case EVENT_BUILD_HARPOON_1:
+ BuildHarpoon(HARPOON_1);
+ _building = false;
+ break;
+ case EVENT_BUILD_HARPOON_2:
+ BuildHarpoon(HARPOON_2);
+ _building = false;
+ break;
+ case EVENT_BUILD_HARPOON_3:
+ BuildHarpoon(HARPOON_3);
+ _building = false;
+ break;
+ case EVENT_BUILD_HARPOON_4:
+ BuildHarpoon(HARPOON_4);
+ _building = false;
+ break;
+ case EVENT_HANDLE_DESTROY_HARPOON:
+ _destroy = false;
+ break;
+ default:
+ break;
}
+ }
+ }
+
+private:
+ InstanceScript* _instance;
+ GuidVector _harpoons;
+ bool _is25Man;
+ bool _building;
+ bool _destroy;
+ bool _stopControllers;
+ EventMap _events;
+};
- InstanceScript* instance;
- SummonList summons;
+struct npc_expedition_defender : public ScriptedAI
+{
+ npc_expedition_defender(Creature* creature) : ScriptedAI(creature), _myPositionNumber(0), _instance(creature->GetInstanceScript())
+ {
+ me->SetRegenerateHealth(false);
+ }
+
+ void Reset() override
+ {
+ DoCastSelf(SPELL_THREAT);
+ }
+
+ bool CanAIAttack(Unit const* target) const override
+ {
+ if (target->GetEntry() == NPC_RAZORSCALE || target->GetEntry() == NPC_RAZORSCALE_SPAWNER)
+ return false;
- bool Greet;
- uint32 AttackStartTimer;
- uint8 Phase;
- ObjectGuid Engineer[4];
- ObjectGuid Defender[4];
+ return ScriptedAI::CanAIAttack(target);
+ }
+
+ void SetData(uint32 type, uint32 value) override
+ {
+ if (type == DATA_EXPEDITION_NUMBER)
+ _myPositionNumber = value;
+ }
+
+ void DoAction(int32 actionId) override
+ {
+ if (actionId == ACTION_START_FIGHT)
+ me->GetMotionMaster()->MovePoint(POINT_DEFENDER_ATTACK, DefendersPosition[_myPositionNumber]);
+ }
+
+ void MovementInform(uint32 type, uint32 pointId) override
+ {
+ if (type != POINT_MOTION_TYPE && pointId != POINT_DEFENDER_ATTACK)
+ return;
+
+ me->SetHomePosition(DefendersPosition[_myPositionNumber]);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC);
+ }
+
+private:
+ uint8 _myPositionNumber;
+ InstanceScript* _instance;
+};
- void Reset() override
- {
- Initialize();
- summons.DespawnAll();
- }
+struct npc_expedition_trapper : public ScriptedAI
+{
+ npc_expedition_trapper(Creature* creature) : ScriptedAI(creature), _myPositionNumber(0), _instance(creature->GetInstanceScript())
+ {
+ SetCombatMovement(false);
+ me->SetReactState(REACT_PASSIVE);
+ }
+
+ void DoAction(int32 actionId) override
+ {
+ if (!me->IsAlive())
+ return;
+
+ switch (actionId)
+ {
+ case ACTION_SHACKLE_RAZORSCALE:
+ me->GetMotionMaster()->MovePoint(POINT_SHACKLE_RAZORSCALE, TrapperPosition[_myPositionNumber]);
+ break;
+ case ACTION_RETURN_TO_BASE:
+ me->GetMotionMaster()->MoveTargetedHome();
+ break;
+ case ACTION_START_FIGHT:
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC);
+ break;
+ case ACTION_STOP_CAST:
+ me->InterruptNonMeleeSpells(false);
+ _scheduler.Schedule(Seconds(2), [this](TaskContext /*context*/)
+ {
+ me->GetMotionMaster()->MoveTargetedHome();
+ });
+ if (Creature* commander = _instance->GetCreature(DATA_EXPEDITION_COMMANDER))
+ commander->AI()->DoAction(ACTION_STOP_CONTROLLERS);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void SetData(uint32 type, uint32 value) override
+ {
+ if (type == DATA_EXPEDITION_NUMBER)
+ _myPositionNumber = value;
+ }
+
+ void MovementInform(uint32 type, uint32 pointId) override
+ {
+ if (type != POINT_MOTION_TYPE && pointId != POINT_SHACKLE_RAZORSCALE)
+ return;
+
+ DoCastSelf(SPELL_SHACKLE);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ _scheduler.Update(diff);
+ }
+
+private:
+ uint8 _myPositionNumber;
+ InstanceScript* _instance;
+ TaskScheduler _scheduler;
+};
- void MoveInLineOfSight(Unit* who) override
+struct npc_expedition_engineer : public ScriptedAI
+{
+ npc_expedition_engineer(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _myPositionNumber(0), _canUpdateAI(false) { }
- {
- if (!Greet && me->IsWithinDistInMap(who, 10.0f) && who->GetTypeId() == TYPEID_PLAYER)
- {
- Talk(SAY_INTRO);
- Greet = true;
- }
- }
+ void Reset() override
+ {
+ me->SetReactState(REACT_PASSIVE);
+ _scheduler.CancelAll();
+ }
- void JustSummoned(Creature* summoned) override
- {
- summons.Summon(summoned);
- }
+ void DoAction(int32 actionId) override
+ {
+ if (!me->IsAlive())
+ return;
- void DoAction(int32 action) override
+ if (actionId == ACTION_START_FIGHT)
+ {
+ _canUpdateAI = true;
+ if (_myPositionNumber == ENGINEER_EAST)
+ Talk(SAY_AGGRO);
+ _scheduler.Schedule(Seconds(28), [this](TaskContext /*context*/)
{
- switch (action)
- {
- case ACTION_GROUND_PHASE:
- Talk(SAY_GROUND_PHASE);
- break;
- case ACTION_COMMANDER_RESET:
- summons.DespawnAll();
- me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
- break;
- }
- }
-
- void UpdateAI(uint32 Diff) override
+ HandleHarpoonMovement();
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC);
+ });
+ }
+ else if (actionId == ACTION_FIX_HARPOONS)
+ {
+ if (_myPositionNumber == ENGINEER_EAST)
+ Talk(SAY_AGGRO);
+ _scheduler.Schedule(Seconds(28), [this](TaskContext /*context*/)
{
- if (AttackStartTimer <= Diff)
- {
- switch (Phase)
- {
- case 1:
- instance->SetBossState(BOSS_RAZORSCALE, IN_PROGRESS);
- summons.DespawnAll();
- AttackStartTimer = 1000;
- Phase = 2;
- break;
- case 2:
- for (uint8 n = 0; n < RAID_MODE(2, 4); n++)
- {
- if (Creature* summonedEngineer = me->SummonCreature(NPC_ENGINEER, PosEngSpawn, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000))
- {
- summonedEngineer->SetWalk(false);
- summonedEngineer->SetSpeedRate(MOVE_RUN, 0.5f);
- summonedEngineer->SetHomePosition(PosEngRepair[n]);
- summonedEngineer->GetMotionMaster()->MoveTargetedHome();
- Engineer[n] = summonedEngineer->GetGUID();
- }
- }
- if (Creature* firstSummon = ObjectAccessor::GetCreature(*me, Engineer[0]))
- firstSummon->AI()->Talk(SAY_AGGRO_3);
- Phase = 3;
- AttackStartTimer = 14000;
- break;
- case 3:
- for (uint8 n = 0; n < 4; n++)
- {
- if (Creature* summonedDefender = me->SummonCreature(NPC_DEFENDER, PosDefSpawn[n], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000))
- {
- summonedDefender->SetWalk(false);
- summonedDefender->SetHomePosition(PosDefCombat[n]);
- summonedDefender->GetMotionMaster()->MoveTargetedHome();
- Defender[n] = summonedDefender->GetGUID();
- }
- }
- Phase = 4;
- break;
- case 4:
- for (uint8 n = 0; n < RAID_MODE(2, 4); n++)
- if (Creature* summonedEngineer = ObjectAccessor::GetCreature(*me, Engineer[n]))
- summonedEngineer->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_USE_STANDING);
- for (uint8 n = 0; n < 4; ++n)
- if (Creature* summonedDefender = ObjectAccessor::GetCreature(*me, Defender[n]))
- summonedDefender->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H);
- Talk(SAY_AGGRO_2);
- AttackStartTimer = 16000;
- Phase = 5;
- break;
- case 5:
- if (Creature* razorscale = instance->GetCreature(BOSS_RAZORSCALE))
- {
- razorscale->AI()->DoAction(ACTION_EVENT_START);
- me->SetInCombatWith(razorscale);
- }
- if (Creature* firstEngineer = ObjectAccessor::GetCreature(*me, Engineer[0]))
- firstEngineer->AI()->Talk(SAY_AGGRO_1);
- Phase = 6;
- break;
- }
- }
- else
- AttackStartTimer -= Diff;
- }
+ HandleHarpoonMovement();
+ });
+ }
+ }
- bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
- {
- uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
- ClearGossipMenuFor(player);
- switch (action)
- {
- case GOSSIP_ACTION_INFO_DEF:
- CloseGossipMenuFor(player);
- Phase = 1;
- break;
- }
- return true;
- }
+ void ChangeOrientation(float orientation)
+ {
+ _scheduler.Schedule(Milliseconds(1), [this, orientation](TaskContext /*context*/)
+ {
+ me->SetFacingTo(orientation);
+ });
+ }
- bool GossipHello(Player* player) override
- {
- if (instance->GetBossState(BOSS_RAZORSCALE) == NOT_STARTED)
- {
- player->PrepareGossipMenu(me);
+ void HandleHarpoonMovement()
+ {
+ switch (_myPositionNumber)
+ {
+ case ENGINEER_NORTH:
+ if (Is25ManRaid())
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_HARPOON_1_25, SPLINE_ENGINEER_NORTH_25_HARPOON_1, false);
+ else
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_HARPOON_1, SPLINE_ENGINEER_NORTH_10_HARPOON_1, false);
+ break;
+ case ENGINEER_EAST:
+ Talk(SAY_START_REPAIR);
+ if (Is25ManRaid())
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_HARPOON_1_25, SPLINE_ENGINEER_EAST_25_HARPOON_1, false);
+ else
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_HARPOON_1, SPLINE_ENGINEER_EAST_10_HARPOON_1, false);
+ break;
+ case ENGINEER_WEST:
+ if (Is25ManRaid())
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_HARPOON_1_25, SPLINE_ENGINEER_WEST_25_HARPOON_1, false);
+ else
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_HARPOON_1, SPLINE_ENGINEER_WEST_10_HARPOON_1, false);
+ break;
+ default:
+ break;
+ }
+ }
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
- SendGossipMenuFor(player, 13853, me->GetGUID());
- }
+ void HandleSecondHarpoonMovement()
+ {
+ switch (_myPositionNumber)
+ {
+ case ENGINEER_NORTH:
+ if (Is25ManRaid())
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_HARPOON_2_25, SPLINE_ENGINEER_NORTH_25_HARPOON_2, false);
+ else
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_HARPOON_2, SPLINE_ENGINEER_NORTH_10_HARPOON_2, false);
+ break;
+ case ENGINEER_EAST:
+ if (Is25ManRaid())
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_HARPOON_2_25, SPLINE_ENGINEER_EAST_25_HARPOON_2, false);
else
- SendGossipMenuFor(player, 13910, me->GetGUID());
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_HARPOON_2, SPLINE_ENGINEER_EAST_10_HARPOON_2, false);
+ break;
+ case ENGINEER_WEST:
+ if (Is25ManRaid())
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_HARPOON_2_25, SPLINE_ENGINEER_WEST_25_HARPOON_2, false);
+ else
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_HARPOON_2, SPLINE_ENGINEER_WEST_10_HARPOON_2, false);
+ break;
+ default:
+ break;
+ }
+ }
- return true;
- }
+ void HandleThirdHarpoonMovement()
+ {
+ switch (_myPositionNumber)
+ {
+ case ENGINEER_NORTH:
+ if (Is25ManRaid())
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_HARPOON_3, SPLINE_ENGINEER_NORTH_25_HARPOON_3, false);
+ else
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_BASE, SPLINE_ENGINEER_NORTH_10_BASE, false);
+ break;
+ case ENGINEER_EAST:
+ if (Is25ManRaid())
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_HARPOON_3, SPLINE_ENGINEER_EAST_25_HARPOON_3, false);
+ else
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_BASE, SPLINE_ENGINEER_EAST_10_BASE, false);
+ break;
+ case ENGINEER_WEST:
+ if (Is25ManRaid())
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_HARPOON_3, SPLINE_ENGINEER_WEST_25_HARPOON_3, false);
+ else
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_BASE, SPLINE_ENGINEER_WEST_10_BASE, false);
+ break;
+ default:
+ break;
+ }
+ }
- };
+ void HandleFourthHarpoonMovement()
+ {
+ switch (_myPositionNumber)
+ {
+ case ENGINEER_NORTH:
+ if (Is25ManRaid())
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_HARPOON_4, SPLINE_ENGINEER_NORTH_25_HARPOON_4, false);
+ break;
+ case ENGINEER_EAST:
+ if (Is25ManRaid())
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_HARPOON_4, SPLINE_ENGINEER_EAST_25_HARPOON_4, false);
+ break;
+ case ENGINEER_WEST:
+ if (Is25ManRaid())
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_HARPOON_4, SPLINE_ENGINEER_WEST_25_HARPOON_4, false);
+ break;
+ default:
+ break;
+ }
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void HandleBaseMovement()
+ {
+ switch (_myPositionNumber)
{
- return GetUlduarAI<npc_expedition_commanderAI>(creature);
+ case ENGINEER_NORTH:
+ if (Is25ManRaid())
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_BASE, SPLINE_ENGINEER_NORTH_25_BASE, false);
+ break;
+ case ENGINEER_EAST:
+ if (Is25ManRaid())
+ me->GetMotionMaster()->MovePoint(POINT_BASE, me->GetHomePosition());
+ break;
+ case ENGINEER_WEST:
+ if (Is25ManRaid())
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_BASE, SPLINE_ENGINEER_WEST_25_BASE, false);
+ break;
+ default:
+ break;
}
-};
+ }
-class npc_mole_machine_trigger : public CreatureScript
-{
- public:
- npc_mole_machine_trigger() : CreatureScript("npc_mole_machine_trigger") { }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!_canUpdateAI)
+ return;
- struct npc_mole_machine_triggerAI : public ScriptedAI
- {
- npc_mole_machine_triggerAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- SetCombatMovement(false);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PACIFIED);
- }
+ _scheduler.Update(diff);
+ }
- void Initialize()
- {
- SummonGobTimer = 2000;
- SummonNpcTimer = 6000;
- DissapearTimer = 10000;
- GobSummoned = false;
- NpcSummoned = false;
- }
+ void SetData(uint32 type, uint32 value) override
+ {
+ if (type == DATA_EXPEDITION_NUMBER)
+ _myPositionNumber = value;
+ }
- uint32 SummonGobTimer;
- uint32 SummonNpcTimer;
- uint32 DissapearTimer;
- bool GobSummoned;
- bool NpcSummoned;
+ void MovementInform(uint32 type, uint32 pointId) override
+ {
+ if (type != POINT_MOTION_TYPE && type != SPLINE_CHAIN_MOTION_TYPE)
+ return;
- void Reset() override
- {
- Initialize();
- }
+ switch (pointId)
+ {
+ case POINT_HARPOON_1:
+ case POINT_HARPOON_1_25:
+ if (Creature* commander = _instance->GetCreature(DATA_EXPEDITION_COMMANDER))
+ commander->AI()->DoAction(ACTION_BUILD_HARPOON_1);
- void UpdateAI(uint32 Diff) override
- {
- if (!GobSummoned && SummonGobTimer <= Diff)
+ _scheduler.
+ Schedule(Seconds(3), [this](TaskContext /*context*/)
{
- DoCast(SPELL_SUMMON_MOLE_MACHINE);
- GobSummoned = true;
- }
- else
- SummonGobTimer -= Diff;
-
- if (!NpcSummoned && SummonNpcTimer <= Diff)
+ me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_USE_STANDING);
+ })
+ .Schedule(Seconds(18), [this](TaskContext /*context*/)
{
- switch (urand(0, 1 ))
- {
- case 0:
- DoCast(SPELL_SUMMON_IRON_DWARVES);
- break;
- case 1:
- DoCast(SPELL_SUMMON_IRON_DWARVES_2);
- break;
- }
-
- DoCast(SPELL_SUMMON_IRON_DWARVE_GUARDIAN);
- DoCast(SPELL_SUMMON_IRON_DWARVE_WATCHER);
- NpcSummoned = true;
- }
- else
- SummonNpcTimer -= Diff;
-
- if (DissapearTimer <= Diff)
+ HandleSecondHarpoonMovement();
+ });
+ break;
+ case POINT_HARPOON_2:
+ case POINT_HARPOON_2_25:
+ if (Creature* commander = _instance->GetCreature(DATA_EXPEDITION_COMMANDER))
+ commander->AI()->DoAction(ACTION_BUILD_HARPOON_2);
+ _scheduler.Schedule(Seconds(18), [this](TaskContext /*context*/)
{
- if (GameObject* molemachine = me->FindNearestGameObject(GO_MOLE_MACHINE, 1))
- molemachine->Delete();
-
- me->DisappearAndDie();
- }
- else
- DissapearTimer -= Diff;
- }
+ HandleThirdHarpoonMovement();
+ });
+ break;
+ case POINT_HARPOON_3:
+ if (Creature* commander = _instance->GetCreature(DATA_EXPEDITION_COMMANDER))
+ commander->AI()->DoAction(ACTION_BUILD_HARPOON_3);
+ _scheduler.Schedule(Seconds(18), [this](TaskContext /*context*/)
+ {
+ HandleFourthHarpoonMovement();
+ });
+ break;
+ case POINT_HARPOON_4:
+ if (Creature* commander = _instance->GetCreature(DATA_EXPEDITION_COMMANDER))
+ commander->AI()->DoAction(ACTION_BUILD_HARPOON_4);
+ _scheduler.Schedule(Seconds(18), [this](TaskContext /*context*/)
+ {
+ HandleBaseMovement();
+ });
+ break;
+ case POINT_BASE:
+ ChangeOrientation(4.61684f);
+ break;
+ default:
+ break;
+ }
+ }
- void JustSummoned(Creature* summoned) override
- {
- summoned->AI()->DoZoneInCombat();
- }
- };
+private:
+ InstanceScript* _instance;
+ TaskScheduler _scheduler;
+ uint8 _myPositionNumber;
+ bool _canUpdateAI;
+};
- CreatureAI* GetAI(Creature* creature) const override
+struct npc_razorscale_spawner : public ScriptedAI
+{
+ npc_razorscale_spawner(Creature* creature) : ScriptedAI(creature) { }
+
+ void Reset() override
+ {
+ me->setActive(true);
+ me->SetReactState(REACT_PASSIVE);
+ _scheduler.
+ Schedule(Seconds(1), [this](TaskContext /*context*/)
{
- return GetUlduarAI<npc_mole_machine_triggerAI>(creature);
- }
+ DoCastSelf(SPELL_SUMMON_MOLE_MACHINE);
+ }).Schedule(Seconds(6), [this](TaskContext /*context*/)
+ {
+ DoCastSelf(SummonMinionsSpells[urand(0, 3)]);
+ });
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ _scheduler.Update(diff);
+ }
+
+private:
+ TaskScheduler _scheduler;
};
-class npc_devouring_flame : public CreatureScript
+struct npc_darkrune_watcher : public ScriptedAI
{
- public:
- npc_devouring_flame() : CreatureScript("npc_devouring_flame") { }
-
- struct npc_devouring_flameAI : public ScriptedAI
+ npc_darkrune_watcher(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
+
+ void Reset() override
+ {
+ _events.Reset();
+ me->SetReactState(REACT_PASSIVE);
+ _events.ScheduleEvent(EVENT_START_COMBAT, Seconds(2));
+ if (Creature* razorscale = _instance->GetCreature(BOSS_RAZORSCALE))
+ razorscale->AI()->JustSummoned(me);
+ }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_LIGHTNING_BOLT, Seconds(5));
+ _events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, Seconds(34));
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = _events.ExecuteEvent())
{
- npc_devouring_flameAI(Creature* creature) : ScriptedAI(creature)
+ switch (eventId)
{
- SetCombatMovement(false);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PACIFIED);
+ case EVENT_START_COMBAT:
+ me->SetReactState(REACT_AGGRESSIVE);
+ me->SetInCombatWithZone();
+ break;
+ case EVENT_LIGHTNING_BOLT:
+ DoCastVictim(LIGHTNING_BOLT);
+ _events.Repeat(Seconds(3));
+ break;
+ case EVENT_CHAIN_LIGHTNING:
+ DoCastVictim(CHAIN_LIGHTNING);
+ _events.Repeat(Seconds(9), Seconds(15));
+ break;
+ default:
+ break;
}
- void Reset() override
- {
- DoCast(SPELL_FLAME_GROUND);
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetUlduarAI<npc_devouring_flameAI>(creature);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
+
+ DoMeleeAttackIfReady();
+ }
+
+private:
+ InstanceScript* _instance;
+ EventMap _events;
};
-class npc_darkrune_watcher : public CreatureScript
+struct npc_darkrune_guardian : public ScriptedAI
{
- public:
- npc_darkrune_watcher() : CreatureScript("npc_darkrune_watcher") { }
-
- struct npc_darkrune_watcherAI : public ScriptedAI
+ npc_darkrune_guardian(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _killedByBreath(false) { }
+
+ void Reset() override
+ {
+ _events.Reset();
+ me->SetReactState(REACT_PASSIVE);
+ _events.ScheduleEvent(EVENT_START_COMBAT, Seconds(2));
+ if (Creature* razorscale = _instance->GetCreature(BOSS_RAZORSCALE))
+ razorscale->AI()->JustSummoned(me);
+ }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_STORMSTRIKE, Seconds(23));
+ }
+
+ uint32 GetData(uint32 type) const override
+ {
+ return type == DATA_IRON_DWARF_MEDIUM_RARE ? _killedByBreath : 0;
+ }
+
+ void SetData(uint32 type, uint32 value) override
+ {
+ if (type == DATA_IRON_DWARF_MEDIUM_RARE)
+ _killedByBreath = value != 0;
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = _events.ExecuteEvent())
{
- npc_darkrune_watcherAI(Creature* creature) : ScriptedAI(creature)
+ switch (eventId)
{
- Initialize();
+ case EVENT_START_COMBAT:
+ me->SetReactState(REACT_AGGRESSIVE);
+ me->SetInCombatWithZone();
+ break;
+ case EVENT_STORMSTRIKE:
+ DoCastVictim(SPELL_STORMSTRIKE);
+ _events.Repeat(Seconds(13), Seconds(25));
+ break;
+ default:
+ break;
}
- void Initialize()
- {
- ChainTimer = urand(10000, 15000);
- LightTimer = urand(1000, 3000);
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
+
+ DoMeleeAttackIfReady();
+ }
- uint32 ChainTimer;
- uint32 LightTimer;
+private:
+ InstanceScript* _instance;
+ EventMap _events;
+ bool _killedByBreath;
+};
- void Reset() override
+struct npc_darkrune_sentinel : public ScriptedAI
+{
+ npc_darkrune_sentinel(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
+
+ void Reset() override
+ {
+ _events.Reset();
+ me->SetReactState(REACT_PASSIVE);
+ _events.ScheduleEvent(EVENT_START_COMBAT, Seconds(2));
+ if (Creature* razorscale = _instance->GetCreature(BOSS_RAZORSCALE))
+ razorscale->AI()->JustSummoned(me);
+ }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_HEROIC_STRIKE, Seconds(9));
+ _events.ScheduleEvent(EVENT_BATTLE_SHOUT, Seconds(15));
+ _events.ScheduleEvent(EVENT_WHIRLWIND, Seconds(17));
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
{
- Initialize();
+ case EVENT_START_COMBAT:
+ me->SetReactState(REACT_AGGRESSIVE);
+ me->SetInCombatWithZone();
+ break;
+ case EVENT_HEROIC_STRIKE:
+ DoCastVictim(SPELL_HEROIC_STRIKE);
+ _events.Repeat(Seconds(5), Seconds(9));
+ break;
+ case EVENT_BATTLE_SHOUT:
+ DoCastSelf(SPELL_BATTLE_SHOUT);
+ _events.Repeat(Seconds(25));
+ break;
+ case EVENT_WHIRLWIND:
+ DoCastSelf(SPELL_WHIRLWIND);
+ _events.Repeat(Seconds(10), Seconds(13));
+ break;
+ default:
+ break;
}
- void UpdateAI(uint32 Diff) override
- {
- if (!UpdateVictim())
- return;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
- if (ChainTimer <= Diff)
- {
- DoCastVictim(SPELL_CHAIN_LIGHTNING);
- ChainTimer = urand(10000, 15000);
- }
- else
- ChainTimer -= Diff;
+ DoMeleeAttackIfReady();
+ }
- if (LightTimer <= Diff)
- {
- DoCastVictim(SPELL_LIGHTNING_BOLT);
- LightTimer = urand(5000, 7000);
- }
- else
- LightTimer -= Diff;
+private:
+ InstanceScript* _instance;
+ EventMap _events;
+};
- DoMeleeAttackIfReady();
- }
- };
+struct npc_razorscale_harpoon_fire_state : public ScriptedAI
+{
+ npc_razorscale_harpoon_fire_state(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
- CreatureAI* GetAI(Creature* creature) const override
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
+ {
+ if (spell->Id == SPELL_FIREBOLT)
{
- return GetUlduarAI<npc_darkrune_watcherAI>(creature);
+ DoCastSelf(SPELL_HARPOON_FIRE_STATE);
+ if (Creature* commander = _instance->GetCreature(DATA_EXPEDITION_COMMANDER))
+ commander->AI()->DoAction(ACTION_DESTROY_HARPOONS);
}
+ }
+
+private:
+ InstanceScript* _instance;
};
-class npc_darkrune_guardian : public CreatureScript
+struct npc_razorscale_devouring_flame : public ScriptedAI
{
- public:
- npc_darkrune_guardian() : CreatureScript("npc_darkrune_guardian") { }
+ npc_razorscale_devouring_flame(Creature* creature) : ScriptedAI(creature) { }
- struct npc_darkrune_guardianAI : public ScriptedAI
- {
- npc_darkrune_guardianAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- }
+ void Reset() override
+ {
+ DoCastSelf(DEVOURING_FLAME_GROUND);
+ }
+};
- void Initialize()
- {
- StormTimer = urand(3000, 6000);
- killedByBreath = false;
- }
+class go_razorscale_harpoon : public GameObjectScript
+{
+public:
+ go_razorscale_harpoon() : GameObjectScript("go_razorscale_harpoon") { }
- uint32 StormTimer;
+ struct go_razorscale_harpoonAI : public GameObjectAI
+ {
+ go_razorscale_harpoonAI(GameObject* go) : GameObjectAI(go) { }
- void Reset() override
+ void Reset() override
+ {
+ _scheduler.Schedule(Seconds(1), [this](TaskContext /*context*/)
{
- Initialize();
- }
+ if (Creature* controller = me->FindNearestCreature(NPC_RAZORSCALE_CONTROLLER, 5.0f))
+ controller->AI()->Talk(EMOTE_HARPOON);
- uint32 GetData(uint32 type) const override
- {
- return type == DATA_IRON_DWARF_MEDIUM_RARE ? killedByBreath : 0;
- }
+ if (GameObject* brokenHarpoon = me->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f))
+ brokenHarpoon->RemoveFromWorld();
+ });
+ }
- void SetData(uint32 type, uint32 value) override
+ uint32 SelectRightSpell()
+ {
+ switch (me->GetEntry())
{
- if (type == DATA_IRON_DWARF_MEDIUM_RARE)
- killedByBreath = value != 0;
+ case GO_RAZOR_HARPOON_1:
+ return SPELL_HARPOON_SHOT_1;
+ case GO_RAZOR_HARPOON_2:
+ return SPELL_HARPOON_SHOT_2;
+ case GO_RAZOR_HARPOON_3:
+ return SPELL_HARPOON_SHOT_3;
+ case GO_RAZOR_HARPOON_4:
+ return SPELL_HARPOON_SHOT_4;
+ default:
+ return 0;
}
+ }
-
- void UpdateAI(uint32 Diff) override
+ bool GossipHello(Player* /*player*/) override
+ {
+ me->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
+ if (Creature* controller = me->FindNearestCreature(NPC_RAZORSCALE_CONTROLLER, 5.0f))
{
- if (!UpdateVictim())
- return;
+ // Prevent 2 players clicking at "same time"
+ if (controller->HasUnitState(UNIT_STATE_CASTING))
+ return true;
- if (StormTimer <= Diff)
- {
- DoCastVictim(SPELL_STORMSTRIKE);
- StormTimer = urand(4000, 8000);
- }
- else
- StormTimer -= Diff;
-
- DoMeleeAttackIfReady();
+ uint32 spellId = SelectRightSpell();
+ controller->CastSpell(nullptr, spellId, true);
}
- private:
- bool killedByBreath;
- };
+ return true;
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void UpdateAI(uint32 diff) override
{
- return GetUlduarAI<npc_darkrune_guardianAI>(creature);
+ _scheduler.Update(diff);
}
+
+ private:
+ TaskScheduler _scheduler;
+ };
+
+ GameObjectAI* GetAI(GameObject* go) const override
+ {
+ return GetUlduarAI<go_razorscale_harpoonAI>(go);
+ }
};
-class npc_darkrune_sentinel : public CreatureScript
+class go_razorscale_mole_machine : public GameObjectScript
{
- public:
- npc_darkrune_sentinel() : CreatureScript("npc_darkrune_sentinel") { }
+public:
+ go_razorscale_mole_machine() : GameObjectScript("go_razorscale_mole_machine") { }
- struct npc_darkrune_sentinelAI : public ScriptedAI
+ struct go_razorscale_mole_machineAI : public GameObjectAI
+ {
+ go_razorscale_mole_machineAI(GameObject* go) : GameObjectAI(go) { }
+
+ void Reset() override
{
- npc_darkrune_sentinelAI(Creature* creature) : ScriptedAI(creature)
+ me->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
+ _scheduler.Schedule(Seconds(1), [this](TaskContext /*context*/)
{
- Initialize();
- }
-
- void Initialize()
+ me->UseDoorOrButton();
+ });
+ _scheduler.Schedule(Seconds(10), [this](TaskContext /*context*/)
{
- HeroicTimer = urand(4000, 8000);
- WhirlTimer = urand(20000, 25000);
- ShoutTimer = urand(15000, 30000);
- }
-
- uint32 HeroicTimer;
- uint32 WhirlTimer;
- uint32 ShoutTimer;
-
- void Reset() override
- {
- Initialize();
- }
+ me->Delete();
+ });
+ }
- void UpdateAI(uint32 Diff) override
- {
- if (!UpdateVictim())
- return;
+ void UpdateAI(uint32 diff) override
+ {
+ _scheduler.Update(diff);
+ }
- if (HeroicTimer <= Diff)
- {
- DoCastVictim(SPELL_HEROIC_STRIKE);
- HeroicTimer = urand(4000, 6000);
- }
- else
- HeroicTimer -= Diff;
+ private:
+ TaskScheduler _scheduler;
+ };
+ GameObjectAI* GetAI(GameObject* go) const override
+ {
+ return GetUlduarAI<go_razorscale_mole_machineAI>(go);
+ }
+};
- if (WhirlTimer <= Diff)
- {
- DoCastVictim(SPELL_WHIRLWIND);
- WhirlTimer = urand(20000, 25000);
- }
- else
- WhirlTimer -= Diff;
+/* 63317 - Flame Breath
+ 64021 - Flame Breath */
+class spell_razorscale_flame_breath : public SpellScript
+{
+ PrepareSpellScript(spell_razorscale_flame_breath);
- if (ShoutTimer <= Diff)
- {
- DoCast(me, SPELL_BATTLE_SHOUT);
- ShoutTimer = urand(30000, 40000);
- }
- else
- ShoutTimer -= Diff;
+ void CheckDamage()
+ {
+ Creature* target = GetHitCreature();
+ if (!target || target->GetEntry() != NPC_DARK_RUNE_GUARDIAN || !target->IsAlive())
+ return;
- DoMeleeAttackIfReady();
- }
- };
+ if (GetHitDamage() >= int32(target->GetHealth()))
+ target->AI()->SetData(DATA_IRON_DWARF_MEDIUM_RARE, 1);
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ targets.remove_if([](WorldObject* obj)
{
- return GetUlduarAI<npc_darkrune_sentinelAI>(creature);
- }
+ if (Creature* target = obj->ToCreature())
+ if (target->IsTrigger())
+ return true;
+
+ return false;
+ });
+ }
+
+ void Register() override
+ {
+ OnHit += SpellHitFn(spell_razorscale_flame_breath::CheckDamage);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_razorscale_flame_breath::FilterTargets, EFFECT_1, TARGET_UNIT_CONE_ENTRY);
+ }
};
-class spell_razorscale_devouring_flame : public SpellScriptLoader
+/* 63968 - Summon Iron Dwarves
+ 63970 - Summon Iron Dwarves
+ 63969 - Summon Iron Dwarves */
+class spell_razorscale_summon_iron_dwarves : public SpellScript
{
- public:
- spell_razorscale_devouring_flame() : SpellScriptLoader("spell_razorscale_devouring_flame") { }
+ PrepareSpellScript(spell_razorscale_summon_iron_dwarves);
- class spell_razorscale_devouring_flame_SpellScript : public SpellScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareSpellScript(spell_razorscale_devouring_flame_SpellScript);
-
- void HandleSummon(SpellEffIndex effIndex)
- {
- PreventHitDefaultEffect(effIndex);
- Unit* caster = GetCaster();
- uint32 entry = uint32(GetSpellInfo()->Effects[effIndex].MiscValue);
- WorldLocation const* summonLocation = GetExplTargetDest();
- if (!caster || !summonLocation)
- return;
-
- caster->SummonCreature(entry, summonLocation->GetPositionX(), summonLocation->GetPositionY(), GROUND_Z, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 20000);
- }
-
- void Register() override
- {
- OnEffectHit += SpellEffectFn(spell_razorscale_devouring_flame_SpellScript::HandleSummon, EFFECT_0, SPELL_EFFECT_SUMMON);
- }
- };
-
- SpellScript* GetSpellScript() const override
+ SPELL_SUMMON_IRON_DWARF_GUARDIAN,
+ SPELL_SUMMON_IRON_DWARF_WATCHER
+ });
+ }
+
+ void HandleScriptEffect(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ switch (GetSpellInfo()->Id)
{
- return new spell_razorscale_devouring_flame_SpellScript();
+ case SPELL_TRIGGER_SUMMON_IRON_DWARVES:
+ caster->CastSpell(caster, SPELL_SUMMON_IRON_DWARF_GUARDIAN, true);
+ caster->CastSpell(caster, SPELL_SUMMON_IRON_DWARF_GUARDIAN, true);
+ caster->CastSpell(caster, SPELL_SUMMON_IRON_DWARF_WATCHER, true);
+ break;
+ case SPELL_TRIGGER_SUMMON_IRON_DWARVES_2:
+ case SPELL_TRIGGER_SUMMON_IRON_DWARVES_3:
+ caster->CastSpell(caster, SPELL_SUMMON_IRON_DWARF_GUARDIAN, true);
+ caster->CastSpell(caster, SPELL_SUMMON_IRON_DWARF_WATCHER, true);
+ caster->CastSpell(caster, SPELL_SUMMON_IRON_DWARF_WATCHER, true);
+ break;
+ default:
+ break;
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_razorscale_summon_iron_dwarves::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
-class spell_razorscale_flame_breath : public SpellScriptLoader
+// 64771 - Fuse Armor
+class spell_razorscale_fuse_armor : public AuraScript
{
- public:
- spell_razorscale_flame_breath() : SpellScriptLoader("spell_razorscale_flame_breath") { }
-
- class spell_razorscale_flame_breath_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_razorscale_flame_breath_SpellScript);
-
- void CheckDamage()
- {
- Creature* target = GetHitCreature();
- if (!target || target->GetEntry() != NPC_DARK_RUNE_GUARDIAN)
- return;
+ PrepareAuraScript(spell_razorscale_fuse_armor);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_FUSED_ARMOR });
+ }
+
+ void HandleFused(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetStackAmount() == 5)
+ GetTarget()->CastSpell(GetTarget(), SPELL_FUSED_ARMOR, true);
+ }
+
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectRemoveFn(spell_razorscale_fuse_armor::HandleFused, EFFECT_1, SPELL_AURA_MOD_MELEE_HASTE, AURA_EFFECT_HANDLE_REAL);
+ }
+};
- if (GetHitDamage() >= int32(target->GetHealth()))
- target->AI()->SetData(DATA_IRON_DWARF_MEDIUM_RARE, 1);
- }
+// 62669 - Firebolt
+class spell_razorscale_firebolt : public SpellScript
+{
+ PrepareSpellScript(spell_razorscale_firebolt);
- void Register() override
- {
- OnHit += SpellHitFn(spell_razorscale_flame_breath_SpellScript::CheckDamage);
- }
- };
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ targets.remove_if([](WorldObject* obj) { return obj->GetEntry() != NPC_RAZORSCALE_HARPOON_FIRE_STATE; });
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_razorscale_flame_breath_SpellScript();
- }
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_razorscale_firebolt::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
+ }
};
class achievement_iron_dwarf_medium_rare : public AchievementCriteriaScript
{
public:
- achievement_iron_dwarf_medium_rare() : AchievementCriteriaScript("achievement_iron_dwarf_medium_rare")
- {
- }
+ achievement_iron_dwarf_medium_rare() : AchievementCriteriaScript("achievement_iron_dwarf_medium_rare") { }
bool OnCheck(Player* /*player*/, Unit* target) override
{
@@ -1183,17 +1723,23 @@ class achievement_quick_shave : public AchievementCriteriaScript
void AddSC_boss_razorscale()
{
- new boss_razorscale_controller();
+ RegisterUlduarCreatureAI(boss_razorscale);
+ RegisterUlduarCreatureAI(npc_expedition_defender);
+ RegisterUlduarCreatureAI(npc_expedition_trapper);
+ RegisterUlduarCreatureAI(npc_expedition_engineer);
+ RegisterUlduarCreatureAI(npc_expedition_commander);
+ RegisterUlduarCreatureAI(npc_razorscale_spawner);
+ RegisterUlduarCreatureAI(npc_darkrune_watcher);
+ RegisterUlduarCreatureAI(npc_darkrune_guardian);
+ RegisterUlduarCreatureAI(npc_darkrune_sentinel);
+ RegisterUlduarCreatureAI(npc_razorscale_harpoon_fire_state);
+ RegisterUlduarCreatureAI(npc_razorscale_devouring_flame);
new go_razorscale_harpoon();
- new boss_razorscale();
- new npc_expedition_commander();
- new npc_mole_machine_trigger();
- new npc_devouring_flame();
- new npc_darkrune_watcher();
- new npc_darkrune_guardian();
- new npc_darkrune_sentinel();
- new spell_razorscale_devouring_flame();
- new spell_razorscale_flame_breath();
+ new go_razorscale_mole_machine();
+ RegisterSpellScript(spell_razorscale_flame_breath);
+ RegisterSpellScript(spell_razorscale_summon_iron_dwarves);
+ RegisterAuraScript(spell_razorscale_fuse_armor);
+ RegisterSpellScript(spell_razorscale_firebolt);
new achievement_iron_dwarf_medium_rare();
new achievement_quick_shave();
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp
index 9c6cffcba13..8b618c8b271 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp
@@ -375,7 +375,7 @@ class RunicSmashExplosionEvent : public BasicEvent
bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override
{
- _owner->CastSpell((Unit*)nullptr, SPELL_RUNIC_SMASH);
+ _owner->CastSpell(nullptr, SPELL_RUNIC_SMASH);
return true;
}
@@ -393,7 +393,7 @@ class TrashJumpEvent : public BasicEvent
switch (_stage)
{
case 0:
- _owner->CastSpell((Unit*)nullptr, SPELL_LEAP);
+ _owner->CastSpell(nullptr, SPELL_LEAP);
++_stage;
_owner->m_Events.AddEvent(this, eventTime + 2000);
return false;
@@ -425,7 +425,7 @@ class LightningFieldEvent : public BasicEvent
{
if (instance->GetBossState(BOSS_THORIM) == IN_PROGRESS)
{
- _owner->CastSpell((Unit*)nullptr, SPELL_LIGHTNING_FIELD);
+ _owner->CastSpell(nullptr, SPELL_LIGHTNING_FIELD);
_owner->m_Events.AddEvent(this, eventTime + 1000);
return false;
}
@@ -515,7 +515,7 @@ class boss_thorim : public CreatureScript
if (Creature* pillar = ObjectAccessor::GetCreature(*me, _activePillarGUID))
{
pillar->CastSpell(pillar, SPELL_LIGHTNING_ORB_CHARGED, true);
- pillar->CastSpell((Unit*)nullptr, SPELL_LIGHTNING_PILLAR_2);
+ pillar->CastSpell(nullptr, SPELL_LIGHTNING_PILLAR_2);
events.ScheduleEvent(EVENT_LIGHTNING_CHARGE, 8000, 0, PHASE_2);
}
}
@@ -1778,7 +1778,7 @@ class spell_thorim_charge_orb : public SpellScriptLoader
void HandleScript()
{
if (Unit* target = GetHitUnit())
- target->CastSpell((Unit*)nullptr, SPELL_LIGHTNING_PILLAR_1, true);
+ target->CastSpell(nullptr, SPELL_LIGHTNING_PILLAR_1, true);
}
void Register() override
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
index c3817b0525b..2dbc0d0dfbb 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
@@ -558,7 +558,7 @@ class boss_voice_of_yogg_saron : public CreatureScript
if (Creature* yogg = instance->GetCreature(BOSS_YOGG_SARON))
{
yogg->AI()->Talk(EMOTE_YOGG_SARON_EXTINGUISH_ALL_LIFE, me);
- yogg->CastSpell((Unit*)nullptr, SPELL_EXTINGUISH_ALL_LIFE, true);
+ yogg->CastSpell(nullptr, SPELL_EXTINGUISH_ALL_LIFE, true);
}
events.ScheduleEvent(EVENT_EXTINGUISH_ALL_LIFE, 10000); // cast it again after a short while, players can survive
break;
@@ -2340,7 +2340,7 @@ class spell_yogg_saron_empowering_shadows_missile : public SpellScriptLoader
void HandleScript(SpellEffIndex /*effIndex*/)
{
if (Unit* target = GetHitUnit())
- target->CastSpell((Unit*)nullptr, SPELL_EMPOWERING_SHADOWS, true);
+ target->CastSpell(nullptr, SPELL_EMPOWERING_SHADOWS, true);
}
void Register() override
@@ -2600,7 +2600,7 @@ class spell_yogg_saron_death_ray_warning_visual : public SpellScriptLoader /
if (Unit* caster = GetCaster())
{
caster->CastSpell(caster, SPELL_DEATH_RAY_PERIODIC, true);
- caster->CastSpell((Unit*)nullptr, SPELL_DEATH_RAY_DAMAGE_VISUAL, true);
+ caster->CastSpell(nullptr, SPELL_DEATH_RAY_DAMAGE_VISUAL, true);
// TODO: set better movement
caster->GetMotionMaster()->MoveConfused();
}
@@ -2778,7 +2778,7 @@ class spell_yogg_saron_induce_madness : public SpellScriptLoader // 64059
void ClearShatteredIllusion()
{
- GetCaster()->CastSpell((Unit*)nullptr, SPELL_SHATTERED_ILLUSION_REMOVE);
+ GetCaster()->CastSpell(nullptr, SPELL_SHATTERED_ILLUSION_REMOVE);
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
if (Creature* voice = instance->GetCreature(DATA_VOICE_OF_YOGG_SARON))
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
index bd1d2b9c3b6..9c202f2066b 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
@@ -496,10 +496,6 @@ class instance_ulduar : public InstanceMapScript
if (GetBossState(BOSS_LEVIATHAN) == DONE)
gameObject->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
break;
- case GO_MOLE_MACHINE:
- if (GetBossState(BOSS_RAZORSCALE) == IN_PROGRESS)
- gameObject->SetGoState(GO_STATE_ACTIVE);
- break;
case GO_BRAIN_ROOM_DOOR_1:
BrainRoomDoorGUIDs[0] = gameObject->GetGUID();
break;
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
index 4548eac4b97..1a0d57ab691 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
@@ -59,9 +59,7 @@ enum UlduarNPCs
NPC_SALVAGED_CHOPPER = 33062,
NPC_IGNIS = 33118,
NPC_RAZORSCALE = 33186,
- NPC_RAZORSCALE_CONTROLLER = 33233,
NPC_STEELFORGED_DEFFENDER = 33236,
- NPC_EXPEDITION_COMMANDER = 33210,
NPC_XT002 = 33293,
NPC_XT_TOY_PILE = 33337,
NPC_STEELBREAKER = 32867,
@@ -82,6 +80,18 @@ enum UlduarNPCs
NPC_YOGG_SARON = 33288,
NPC_ALGALON = 32871,
+ // Razorscale
+ NPC_DARK_RUNE_GUARDIAN = 33388,
+ NPC_DARK_RUNE_SENTINEL = 33846,
+ NPC_DARK_RUNE_WATCHER = 33453,
+ NPC_RAZORSCALE_SPAWNER = 33245,
+ NPC_EXPEDITION_COMMANDER = 33210,
+ NPC_EXPEDITION_ENGINEER = 33287,
+ NPC_EXPEDITION_DEFENDER = 33816,
+ NPC_EXPEDITION_TRAPPER = 33259,
+ NPC_RAZORSCALE_CONTROLLER = 33233,
+ NPC_RAZORSCALE_HARPOON_FIRE_STATE = 33282,
+
//XT002
NPC_XS013_SCRAPBOT = 33343,
@@ -498,6 +508,8 @@ inline AI* GetUlduarAI(T* obj)
return GetInstanceAI<AI, T>(obj, UlduarScriptName);
}
+#define RegisterUlduarCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetUlduarAI)
+
class KeeperDespawnEvent : public BasicEvent
{
public:
diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp
index 968210df209..3ead66593a6 100644
--- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp
+++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp
@@ -342,7 +342,7 @@ public:
void Reset() override
{
me->SetReactState(REACT_PASSIVE);
- me->setRegeneratingHealth(false);
+ me->SetRegenerateHealth(false);
me->SetSpeedRate(MOVE_RUN, 2.5f);
}
@@ -855,7 +855,7 @@ class spell_summon_gauntlet_mobs_periodic : public SpellScriptLoader
for (uint8 i = 0; i < 2; ++i)
{
uint32 spellId = SummonSpellsList.front();
- GetTarget()->CastSpell((Unit*)nullptr, spellId, true);
+ GetTarget()->CastSpell(nullptr, spellId, true);
SummonSpellsList.push_back(spellId);
SummonSpellsList.pop_front();
}
diff --git a/src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp
index 03ee2289818..ded80918b1c 100644
--- a/src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp
+++ b/src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp
@@ -243,12 +243,12 @@ class spell_archavon_rock_shards : public SpellScriptLoader
for (uint8 i = 0; i < 3; ++i)
{
- caster->CastSpell((Unit*)nullptr, SPELL_ROCK_SHARDS_VISUAL_L, true);
- caster->CastSpell((Unit*)nullptr, SPELL_ROCK_SHARDS_VISUAL_R, true);
+ caster->CastSpell(nullptr, SPELL_ROCK_SHARDS_VISUAL_L, true);
+ caster->CastSpell(nullptr, SPELL_ROCK_SHARDS_VISUAL_R, true);
}
- caster->CastSpell((Unit*)nullptr, SPELL_ROCK_SHARDS_DAMAGE_L, true);
- caster->CastSpell((Unit*)nullptr, SPELL_ROCK_SHARDS_DAMAGE_R, true);
+ caster->CastSpell(nullptr, SPELL_ROCK_SHARDS_DAMAGE_L, true);
+ caster->CastSpell(nullptr, SPELL_ROCK_SHARDS_DAMAGE_R, true);
}
void Register() override
diff --git a/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp
index 0f785817e9b..d093bb65fa8 100644
--- a/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp
+++ b/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp
@@ -17,28 +17,26 @@
#include "ScriptMgr.h"
#include "InstanceScript.h"
-#include "ObjectAccessor.h"
#include "ScriptedCreature.h"
+#include "SpellScript.h"
#include "vault_of_archavon.h"
enum Spells
{
// Toravon
- SPELL_FREEZING_GROUND = 72090, // don't know cd... using 20 secs.
+ SPELL_FREEZING_GROUND = 72090,
SPELL_FROZEN_ORB = 72091,
- SPELL_WHITEOUT = 72034, // Every 38 sec. cast. (after SPELL_FROZEN_ORB)
+ SPELL_WHITEOUT = 72034,
SPELL_FROZEN_MALLET = 71993,
- // Frost Warder
- SPELL_FROST_BLAST = 72123, // don't know cd... using 20 secs.
- SPELL_FROZEN_MALLET_2 = 72122,
-
// Frozen Orb
- SPELL_FROZEN_ORB_DMG = 72081, // priodic dmg aura
- SPELL_FROZEN_ORB_AURA = 72067, // make visible
+ SPELL_FROZEN_ORB_DMG = 72081,
+ SPELL_FROZEN_ORB_AURA = 72067,
+ SPELL_RANDOM_AGGRO = 72084,
- // Frozen Orb Stalker
- SPELL_FROZEN_ORB_SUMMON = 72093, // summon orb
+ // Frost Warder
+ SPELL_FROST_BLAST = 72123, // don't know cd... using 20 secs.
+ SPELL_FROZEN_MALLET_2 = 72122
};
enum Events
@@ -47,256 +45,159 @@ enum Events
EVENT_FROZEN_ORB = 2,
EVENT_WHITEOUT = 3,
- EVENT_FROST_BLAST = 4,
+ EVENT_FROST_BLAST = 4
};
-enum Creatures
+struct boss_toravon : public BossAI
{
- NPC_FROZEN_ORB = 38456 // 1 in 10 mode and 3 in 25 mode
+ boss_toravon(Creature* creature) : BossAI(creature, DATA_TORAVON) { }
-};
+ void EnterCombat(Unit* /*who*/) override
+ {
+ DoCastSelf(SPELL_FROZEN_MALLET);
-class boss_toravon : public CreatureScript
-{
- public:
- boss_toravon() : CreatureScript("boss_toravon") { }
+ events.ScheduleEvent(EVENT_FROZEN_ORB, Seconds(12));
+ events.ScheduleEvent(EVENT_WHITEOUT, Seconds(25));
+ events.ScheduleEvent(EVENT_FREEZING_GROUND, Seconds(7));
- struct boss_toravonAI : public BossAI
- {
- boss_toravonAI(Creature* creature) : BossAI(creature, DATA_TORAVON)
- {
- }
+ _EnterCombat();
+ }
- void EnterCombat(Unit* /*who*/) override
- {
- DoCast(me, SPELL_FROZEN_MALLET);
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- events.ScheduleEvent(EVENT_FROZEN_ORB, 11000);
- events.ScheduleEvent(EVENT_WHITEOUT, 13000);
- events.ScheduleEvent(EVENT_FREEZING_GROUND, 15000);
+ events.Update(diff);
- _EnterCombat();
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- void UpdateAI(uint32 diff) override
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- if (!UpdateVictim())
- return;
-
- events.Update(diff);
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_FROZEN_ORB:
- me->CastCustomSpell(SPELL_FROZEN_ORB, SPELLVALUE_MAX_TARGETS, 1, me);
- events.ScheduleEvent(EVENT_FROZEN_ORB, 38000);
- break;
- case EVENT_WHITEOUT:
- DoCast(me, SPELL_WHITEOUT);
- events.ScheduleEvent(EVENT_WHITEOUT, 38000);
- break;
- case EVENT_FREEZING_GROUND:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1))
- DoCast(target, SPELL_FREEZING_GROUND);
- events.ScheduleEvent(EVENT_FREEZING_GROUND, 20000);
- break;
- default:
- break;
- }
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- }
-
- DoMeleeAttackIfReady();
+ case EVENT_FROZEN_ORB:
+ me->CastCustomSpell(SPELL_FROZEN_ORB, SPELLVALUE_MAX_TARGETS, RAID_MODE(1, 3), me);
+ events.Repeat(Seconds(32));
+ break;
+ case EVENT_WHITEOUT:
+ DoCastSelf(SPELL_WHITEOUT);
+ events.Repeat(Seconds(38));
+ break;
+ case EVENT_FREEZING_GROUND:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1))
+ DoCast(target, SPELL_FREEZING_GROUND);
+ events.Repeat(Seconds(38));
+ break;
+ default:
+ break;
}
- };
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetVaultOfArchavonAI<boss_toravonAI>(creature);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
+
+ DoMeleeAttackIfReady();
+ }
};
-/*######
-## Mob Frost Warder
-######*/
-class npc_frost_warder : public CreatureScript
+struct npc_frost_warder : public ScriptedAI
{
- public:
- npc_frost_warder() : CreatureScript("npc_frost_warder") { }
-
- struct npc_frost_warderAI : public ScriptedAI
- {
- npc_frost_warderAI(Creature* creature) : ScriptedAI(creature) { }
-
- void Reset() override
- {
- events.Reset();
- }
-
- void EnterCombat(Unit* /*who*/) override
- {
- DoZoneInCombat();
-
- DoCast(me, SPELL_FROZEN_MALLET_2);
+ npc_frost_warder(Creature* creature) : ScriptedAI(creature) { }
- events.ScheduleEvent(EVENT_FROST_BLAST, 5000);
- }
+ void Reset() override
+ {
+ _events.Reset();
+ }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ void EnterCombat(Unit* /*who*/) override
+ {
+ DoZoneInCombat();
- events.Update(diff);
+ DoCastSelf(SPELL_FROZEN_MALLET_2);
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ _events.ScheduleEvent(EVENT_FROST_BLAST, 5000);
+ }
- if (events.ExecuteEvent() == EVENT_FROST_BLAST)
- {
- DoCastVictim(SPELL_FROST_BLAST);
- events.ScheduleEvent(EVENT_FROST_BLAST, 20000);
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- DoMeleeAttackIfReady();
- }
+ _events.Update(diff);
- private:
- EventMap events;
- };
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- CreatureAI* GetAI(Creature* creature) const override
+ if (_events.ExecuteEvent() == EVENT_FROST_BLAST)
{
- return GetVaultOfArchavonAI<npc_frost_warderAI>(creature);
+ DoCastVictim(SPELL_FROST_BLAST);
+ _events.ScheduleEvent(EVENT_FROST_BLAST, 20000);
}
+
+ DoMeleeAttackIfReady();
+ }
+
+private:
+ EventMap _events;
};
-/*######
-## Mob Frozen Orb
-######*/
-class npc_frozen_orb : public CreatureScript
+struct npc_frozen_orb : public ScriptedAI
{
-public:
- npc_frozen_orb() : CreatureScript("npc_frozen_orb") { }
+ npc_frozen_orb(Creature* creature) : ScriptedAI(creature) { }
- struct npc_frozen_orbAI : public ScriptedAI
+ void IsSummonedBy(Unit* /*summoner*/) override
{
- npc_frozen_orbAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- }
+ DoCastSelf(SPELL_FROZEN_ORB_AURA, true);
+ DoCastSelf(SPELL_FROZEN_ORB_DMG, true);
+ DoCastSelf(SPELL_RANDOM_AGGRO, true);
- void Initialize()
+ if (Creature* toravon = me->GetInstanceScript()->GetCreature(DATA_TORAVON))
{
- done = false;
- killTimer = 60000; // if after this time there is no victim -> destroy!
- }
-
- void Reset() override
- {
- Initialize();
- }
-
- void EnterCombat(Unit* /*who*/) override
- {
- DoZoneInCombat();
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (!done)
- {
- DoCast(me, SPELL_FROZEN_ORB_AURA, true);
- DoCast(me, SPELL_FROZEN_ORB_DMG, true);
- done = true;
- }
-
- if (killTimer <= diff)
+ if (toravon->IsInCombat())
{
- if (!UpdateVictim())
- me->DespawnOrUnsummon();
- killTimer = 10000;
+ toravon->AI()->JustSummoned(me);
+ me->SetInCombatWithZone();
}
else
- killTimer -= diff;
+ me->DespawnOrUnsummon();
}
-
- private:
- uint32 killTimer;
- bool done;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetVaultOfArchavonAI<npc_frozen_orbAI>(creature);
}
};
-/*######
-## Mob Frozen Orb Stalker
-######*/
-class npc_frozen_orb_stalker : public CreatureScript
+// 46523 - Random Aggro
+class spell_toravon_random_aggro : public SpellScript
{
- public:
- npc_frozen_orb_stalker() : CreatureScript("npc_frozen_orb_stalker") { }
+ PrepareSpellScript(spell_toravon_random_aggro);
- struct npc_frozen_orb_stalkerAI : public ScriptedAI
- {
- npc_frozen_orb_stalkerAI(Creature* creature) : ScriptedAI(creature)
- {
- creature->SetVisible(false);
- creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
- me->SetControlled(true, UNIT_STATE_ROOT);
- creature->SetReactState(REACT_PASSIVE);
-
- instance = creature->GetInstanceScript();
- spawned = false;
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_UNIT;
+ }
- SetCombatMovement(false);
- }
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Creature* caster = GetCaster()->ToCreature();
+ if (!caster->IsAIEnabled)
+ return;
- void UpdateAI(uint32 /*diff*/) override
- {
- if (spawned)
- return;
-
- spawned = true;
- Unit* toravon = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_TORAVON));
- if (!toravon)
- return;
-
- uint8 num_orbs = RAID_MODE(1, 3);
- for (uint8 i = 0; i < num_orbs; ++i)
- {
- Position pos;
- me->GetNearPoint(toravon, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 0.0f, 10.0f, 0.0f);
- me->UpdatePosition(pos);
- DoCast(me, SPELL_FROZEN_ORB_SUMMON);
- }
- }
+ caster->GetThreatManager().resetAllAggro();
- private:
- InstanceScript* instance;
- bool spawned;
- };
+ if (Unit* target = caster->AI()->SelectTarget(SELECT_TARGET_RANDOM, 1))
+ caster->GetThreatManager().AddThreat(target, 1000000);
+ }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetVaultOfArchavonAI<npc_frozen_orb_stalkerAI>(creature);
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_toravon_random_aggro::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
void AddSC_boss_toravon()
{
- new boss_toravon();
- new npc_frost_warder();
- new npc_frozen_orb();
- new npc_frozen_orb_stalker();
+ RegisterVaultOfArchavonCreatureAI(boss_toravon);
+ RegisterVaultOfArchavonCreatureAI(npc_frost_warder);
+ RegisterVaultOfArchavonCreatureAI(npc_frozen_orb);
+ RegisterSpellScript(spell_toravon_random_aggro);
}
diff --git a/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp
index f399449932f..df562d81546 100644
--- a/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp
+++ b/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp
@@ -16,7 +16,6 @@
*/
#include "ScriptMgr.h"
-#include "Creature.h"
#include "InstanceScript.h"
#include "Map.h"
#include "vault_of_archavon.h"
@@ -28,6 +27,15 @@
4 - Toravon the Ice Watcher event
*/
+ObjectData const creatureData[] =
+{
+ { NPC_ARCHAVON, DATA_ARCHAVON },
+ { NPC_EMALON, DATA_EMALON },
+ { NPC_KORALON, DATA_KORALON },
+ { NPC_TORAVON, DATA_TORAVON },
+ { 0, 0, }
+};
+
class instance_vault_of_archavon : public InstanceMapScript
{
public:
@@ -39,42 +47,13 @@ class instance_vault_of_archavon : public InstanceMapScript
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
+ LoadObjectData(creatureData, nullptr);
ArchavonDeath = 0;
EmalonDeath = 0;
KoralonDeath = 0;
}
- void OnCreatureCreate(Creature* creature) override
- {
- switch (creature->GetEntry())
- {
- case NPC_EMALON:
- EmalonGUID = creature->GetGUID();
- break;
- case NPC_TORAVON:
- ToravonGUID = creature->GetGUID();
- break;
- default:
- break;
- }
- }
-
- ObjectGuid GetGuidData(uint32 identifier) const override
- {
- switch (identifier)
- {
- case DATA_EMALON:
- return EmalonGUID;
- case DATA_TORAVON:
- return ToravonGUID;
- default:
- break;
- }
-
- return ObjectGuid::Empty;
- }
-
bool SetBossState(uint32 type, EncounterState state) override
{
if (!InstanceScript::SetBossState(type, state))
@@ -127,8 +106,6 @@ class instance_vault_of_archavon : public InstanceMapScript
}
private:
- ObjectGuid EmalonGUID;
- ObjectGuid ToravonGUID;
time_t ArchavonDeath;
time_t EmalonDeath;
time_t KoralonDeath;
diff --git a/src/server/scripts/Northrend/VaultOfArchavon/vault_of_archavon.h b/src/server/scripts/Northrend/VaultOfArchavon/vault_of_archavon.h
index d4f252d3715..491ef5dd82d 100644
--- a/src/server/scripts/Northrend/VaultOfArchavon/vault_of_archavon.h
+++ b/src/server/scripts/Northrend/VaultOfArchavon/vault_of_archavon.h
@@ -30,7 +30,7 @@ enum VAData
DATA_ARCHAVON = 0,
DATA_EMALON = 1,
DATA_KORALON = 2,
- DATA_TORAVON = 3,
+ DATA_TORAVON = 3
};
enum VACreatureIds
@@ -44,12 +44,12 @@ enum VACreatureIds
enum VAAchievementCriteriaIds
{
CRITERIA_EARTH_WIND_FIRE_10 = 12018,
- CRITERIA_EARTH_WIND_FIRE_25 = 12019,
+ CRITERIA_EARTH_WIND_FIRE_25 = 12019
};
enum VAAchievementSpells
{
- SPELL_EARTH_WIND_FIRE_ACHIEVEMENT_CHECK = 68308,
+ SPELL_EARTH_WIND_FIRE_ACHIEVEMENT_CHECK = 68308
};
template <class AI, class T>
@@ -58,4 +58,6 @@ inline AI* GetVaultOfArchavonAI(T* obj)
return GetInstanceAI<AI>(obj, VoAScriptName);
}
+#define RegisterVaultOfArchavonCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetVaultOfArchavonAI)
+
#endif
diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp
index e06087a738b..3675973c6e9 100644
--- a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp
+++ b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp
@@ -820,9 +820,9 @@ class npc_violet_hold_teleportation_portal_intro : public CreatureScript
}
};
-struct violet_hold_trashAI : public npc_escortAI
+struct violet_hold_trashAI : public EscortAI
{
- violet_hold_trashAI(Creature* creature) : npc_escortAI(creature)
+ violet_hold_trashAI(Creature* creature) : EscortAI(creature)
{
_instance = creature->GetInstanceScript();
@@ -898,7 +898,7 @@ struct violet_hold_trashAI : public npc_escortAI
}
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (waypointId == _lastWaypointId)
CreatureStartAttackDoor();
@@ -906,7 +906,7 @@ struct violet_hold_trashAI : public npc_escortAI
void EnterCombat(Unit* who) override
{
- npc_escortAI::EnterCombat(who);
+ EscortAI::EnterCombat(who);
ScheduledTasks();
}
@@ -919,7 +919,7 @@ struct violet_hold_trashAI : public npc_escortAI
return;
_scheduler.Update(diff,
- std::bind(&npc_escortAI::DoMeleeAttackIfReady, this));
+ std::bind(&EscortAI::DoMeleeAttackIfReady, this));
}
virtual void ScheduledTasks() { }
diff --git a/src/server/scripts/Northrend/zone_borean_tundra.cpp b/src/server/scripts/Northrend/zone_borean_tundra.cpp
index fccc0a8f437..4b32348ab54 100644
--- a/src/server/scripts/Northrend/zone_borean_tundra.cpp
+++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp
@@ -571,9 +571,9 @@ class npc_lurgglbr : public CreatureScript
public:
npc_lurgglbr() : CreatureScript("npc_lurgglbr") { }
- struct npc_lurgglbrAI : public npc_escortAI
+ struct npc_lurgglbrAI : public EscortAI
{
- npc_lurgglbrAI(Creature* creature) : npc_escortAI(creature)
+ npc_lurgglbrAI(Creature* creature) : EscortAI(creature)
{
Initialize();
}
@@ -593,7 +593,7 @@ public:
Initialize();
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -602,6 +602,7 @@ public:
IntroTimer = 2000;
break;
case 41:
+ SetEscortPaused(true);
IntroPhase = 4;
IntroTimer = 2000;
break;
@@ -628,7 +629,7 @@ public:
IntroTimer = 7500;
break;
case 3:
- me->SetReactState(REACT_AGGRESSIVE);
+ me->SetReactState(REACT_DEFENSIVE);
IntroPhase = 0;
IntroTimer = 0;
break;
@@ -643,14 +644,12 @@ public:
IntroPhase = 6;
IntroTimer = 2500;
break;
-
case 6:
if (Player* player = GetPlayerForEscort())
player->AreaExploredOrEventHappens(QUEST_ESCAPE_WINTERFIN_CAVERNS);
IntroPhase = 7;
IntroTimer = 2500;
break;
-
case 7:
me->DespawnOrUnsummon();
IntroPhase = 0;
@@ -659,7 +658,7 @@ public:
}
} else IntroTimer -= diff;
}
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (!UpdateVictim())
return;
@@ -672,8 +671,7 @@ public:
if (GameObject* go = me->FindNearestGameObject(GO_CAGE, 5.0f))
{
go->SetRespawnTime(0);
- go->SetGoType(GAMEOBJECT_TYPE_BUTTON);
- go->UseDoorOrButton(20);
+ go->UseDoorOrButton(20000);
}
Start(true, false, player->GetGUID());
@@ -794,9 +792,9 @@ class npc_thassarian : public CreatureScript
public:
npc_thassarian() : CreatureScript("npc_thassarian") { }
- struct npc_thassarianAI : public npc_escortAI
+ struct npc_thassarianAI : public EscortAI
{
- npc_thassarianAI(Creature* creature) : npc_escortAI(creature)
+ npc_thassarianAI(Creature* creature) : EscortAI(creature)
{
Initialize();
}
@@ -838,7 +836,7 @@ public:
Initialize();
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
@@ -873,7 +871,7 @@ public:
void UpdateAI(uint32 diff) override
{
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (arthasInPosition && talbotInPosition)
{
@@ -1638,9 +1636,9 @@ class npc_mootoo_the_younger : public CreatureScript
public:
npc_mootoo_the_younger() : CreatureScript("npc_mootoo_the_younger") { }
- struct npc_mootoo_the_youngerAI : public npc_escortAI
+ struct npc_mootoo_the_youngerAI : public EscortAI
{
- npc_mootoo_the_youngerAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_mootoo_the_youngerAI(Creature* creature) : EscortAI(creature) { }
void Reset() override
{
@@ -1653,7 +1651,7 @@ public:
player->FailQuest(QUEST_ESCAPING_THE_MIST);
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
@@ -1727,9 +1725,9 @@ class npc_bonker_togglevolt : public CreatureScript
public:
npc_bonker_togglevolt() : CreatureScript("npc_bonker_togglevolt") { }
- struct npc_bonker_togglevoltAI : public npc_escortAI
+ struct npc_bonker_togglevoltAI : public EscortAI
{
- npc_bonker_togglevoltAI(Creature* creature) : npc_escortAI(creature)
+ npc_bonker_togglevoltAI(Creature* creature) : EscortAI(creature)
{
Initialize();
}
@@ -1767,7 +1765,7 @@ public:
else Bonker_agro=0;
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
@@ -2384,6 +2382,108 @@ public:
}
};
+enum BloodsporeRuination
+{
+ NPC_BLOODMAGE_LAURITH = 25381,
+ SAY_BLOODMAGE_LAURITH = 0,
+ EVENT_TALK = 1,
+ EVENT_RESET_ORIENTATION
+};
+
+class spell_q11719_bloodspore_ruination_45997 : public SpellScriptLoader
+{
+public:
+ spell_q11719_bloodspore_ruination_45997() : SpellScriptLoader("spell_q11719_bloodspore_ruination_45997") { }
+
+ class spell_q11719_bloodspore_ruination_45997_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_q11719_bloodspore_ruination_45997_SpellScript);
+
+ void HandleEffect(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* caster = GetCaster())
+ if (Creature* laurith = caster->FindNearestCreature(NPC_BLOODMAGE_LAURITH, 100.0f))
+ laurith->AI()->SetGUID(caster->GetGUID());
+ }
+
+ void Register() override
+ {
+ OnEffectHit += SpellEffectFn(spell_q11719_bloodspore_ruination_45997_SpellScript::HandleEffect, EFFECT_1, SPELL_EFFECT_SEND_EVENT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_q11719_bloodspore_ruination_45997_SpellScript();
+ }
+};
+
+class npc_bloodmage_laurith : public CreatureScript
+{
+public:
+ npc_bloodmage_laurith() : CreatureScript("npc_bloodmage_laurith") { }
+
+ struct npc_bloodmage_laurithAI : public ScriptedAI
+ {
+ npc_bloodmage_laurithAI(Creature* creature) : ScriptedAI(creature) { }
+
+ void Reset() override
+ {
+ _events.Reset();
+ _playerGUID.Clear();
+ }
+
+ void SetGUID(ObjectGuid guid, int32 /*action*/) override
+ {
+ if (!_playerGUID.IsEmpty())
+ return;
+
+ _playerGUID = guid;
+
+ if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
+ me->SetFacingToObject(player);
+
+ _events.ScheduleEvent(EVENT_TALK, Seconds(1));
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (UpdateVictim())
+ {
+ DoMeleeAttackIfReady();
+ return;
+ }
+
+ _events.Update(diff);
+
+ if (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_TALK:
+ if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
+ Talk(SAY_BLOODMAGE_LAURITH, player);
+ _playerGUID.Clear();
+ _events.ScheduleEvent(EVENT_RESET_ORIENTATION, Seconds(5));
+ break;
+ case EVENT_RESET_ORIENTATION:
+ me->SetFacingTo(me->GetHomePosition().GetOrientation());
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap _events;
+ ObjectGuid _playerGUID;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return new npc_bloodmage_laurithAI(creature);
+ }
+};
+
void AddSC_borean_tundra()
{
new npc_sinkhole_kill_credit();
@@ -2409,4 +2509,6 @@ void AddSC_borean_tundra()
new npc_warmage_coldarra();
new npc_hidden_cultist();
new spell_windsoul_totem_aura();
+ new spell_q11719_bloodspore_ruination_45997();
+ new npc_bloodmage_laurith();
}
diff --git a/src/server/scripts/Northrend/zone_dalaran.cpp b/src/server/scripts/Northrend/zone_dalaran.cpp
index a8920ff3a07..4702d10ed4b 100644
--- a/src/server/scripts/Northrend/zone_dalaran.cpp
+++ b/src/server/scripts/Northrend/zone_dalaran.cpp
@@ -135,14 +135,18 @@ enum MinigobData
{
ZONE_DALARAN = 4395,
- SPELL_MANABONKED = 61834,
+ SPELL_MANABONKED = 61839,
SPELL_TELEPORT_VISUAL = 51347,
SPELL_IMPROVED_BLINK = 61995,
EVENT_SELECT_TARGET = 1,
- EVENT_BLINK = 2,
- EVENT_DESPAWN_VISUAL = 3,
- EVENT_DESPAWN = 4,
+ EVENT_LAUGH_1 = 2,
+ EVENT_WANDER = 3,
+ EVENT_PAUSE = 4,
+ EVENT_CAST = 5,
+ EVENT_LAUGH_2 = 6,
+ EVENT_BLINK = 7,
+ EVENT_DESPAWN = 8,
MAIL_MINIGOB_ENTRY = 264,
MAIL_DELIVER_DELAY_MIN = 5*MINUTE,
@@ -163,26 +167,29 @@ class npc_minigob_manabonk : public CreatureScript
void Reset() override
{
+ playerGuid = ObjectGuid();
me->SetVisible(false);
- events.ScheduleEvent(EVENT_SELECT_TARGET, IN_MILLISECONDS);
+ events.ScheduleEvent(EVENT_SELECT_TARGET, Seconds(1));
}
- Player* SelectTargetInDalaran()
+ void GetPlayersInDalaran(std::vector<Player*>& playerList) const
{
- std::vector<Player*> PlayerInDalaranList;
-
Map::PlayerList const& players = me->GetMap()->GetPlayers();
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
if (Player* player = itr->GetSource()->ToPlayer())
if (player->GetZoneId() == ZONE_DALARAN && !player->IsFlying() && !player->IsMounted() && !player->IsGameMaster())
- PlayerInDalaranList.push_back(player);
+ playerList.push_back(player);
+ }
+ static Player* SelectTargetInDalaran(std::vector<Player*>& PlayerInDalaranList)
+ {
if (PlayerInDalaranList.empty())
return nullptr;
+
return Trinity::Containers::SelectRandomContainerElement(PlayerInDalaranList);
}
- void SendMailToPlayer(Player* player)
+ void SendMailToPlayer(Player* player) const
{
SQLTransaction trans = CharacterDatabase.BeginTransaction();
int16 deliverDelay = irand(MAIL_DELIVER_DELAY_MIN, MAIL_DELIVER_DELAY_MAX);
@@ -199,30 +206,61 @@ class npc_minigob_manabonk : public CreatureScript
switch (eventId)
{
case EVENT_SELECT_TARGET:
+ {
+ std::vector<Player*> PlayerInDalaranList;
+ GetPlayersInDalaran(PlayerInDalaranList);
+
+ // Increases chance of event based on player count in Dalaran (100 players or more = 100% else player count%)
+ if (PlayerInDalaranList.empty() || urand(1, 100) > PlayerInDalaranList.size())
+ me->AddObjectToRemoveList();
+
me->SetVisible(true);
- DoCast(me, SPELL_TELEPORT_VISUAL);
- if (Player* player = SelectTargetInDalaran())
+ DoCastSelf(SPELL_TELEPORT_VISUAL);
+ if (Player* player = SelectTargetInDalaran(PlayerInDalaranList))
+ {
+ playerGuid = player->GetGUID();
+ Position pos = player->GetPosition();
+ float dist = frand(10.0f, 30.0f);
+ float angle = frand(0.0f, 1.0f) * M_PI * 2.0f;
+ player->MovePositionToFirstCollision(pos, dist, angle);
+ me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation());
+ }
+ events.ScheduleEvent(EVENT_LAUGH_1, Seconds(2));
+ break;
+ }
+ case EVENT_LAUGH_1:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_LAUGH_NO_SHEATHE);
+ events.ScheduleEvent(EVENT_WANDER, Seconds(3));
+ break;
+ case EVENT_WANDER:
+ me->GetMotionMaster()->MoveRandom(8);
+ events.ScheduleEvent(EVENT_PAUSE, Minutes(1));
+ break;
+ case EVENT_PAUSE:
+ me->GetMotionMaster()->MoveIdle();
+ events.ScheduleEvent(EVENT_CAST, Seconds(2));
+ break;
+ case EVENT_CAST:
+ if (Player* player = me->GetMap()->GetPlayer(playerGuid))
{
- me->NearTeleportTo(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), 0.0f);
DoCast(player, SPELL_MANABONKED);
SendMailToPlayer(player);
}
- events.ScheduleEvent(EVENT_BLINK, 3*IN_MILLISECONDS);
+ else
+ me->AddObjectToRemoveList();
+
+ events.ScheduleEvent(EVENT_LAUGH_2, Seconds(8));
break;
- case EVENT_BLINK:
- {
- DoCast(me, SPELL_IMPROVED_BLINK);
- Position pos = me->GetRandomNearPosition(frand(15, 40));
- me->GetMotionMaster()->MovePoint(0, pos.m_positionX, pos.m_positionY, pos.m_positionZ);
- events.ScheduleEvent(EVENT_DESPAWN, 3 * IN_MILLISECONDS);
- events.ScheduleEvent(EVENT_DESPAWN_VISUAL, 2.5*IN_MILLISECONDS);
+ case EVENT_LAUGH_2:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_LAUGH_NO_SHEATHE);
+ events.ScheduleEvent(EVENT_BLINK, Seconds(3));
break;
- }
- case EVENT_DESPAWN_VISUAL:
- DoCast(me, SPELL_TELEPORT_VISUAL);
+ case EVENT_BLINK:
+ DoCastSelf(SPELL_IMPROVED_BLINK);
+ events.ScheduleEvent(EVENT_DESPAWN, Seconds(4));
break;
case EVENT_DESPAWN:
- me->DespawnOrUnsummon();
+ me->AddObjectToRemoveList();
break;
default:
break;
@@ -231,6 +269,8 @@ class npc_minigob_manabonk : public CreatureScript
}
private:
+
+ ObjectGuid playerGuid;
EventMap events;
};
diff --git a/src/server/scripts/Northrend/zone_dragonblight.cpp b/src/server/scripts/Northrend/zone_dragonblight.cpp
index 43983271833..6af5973eab0 100644
--- a/src/server/scripts/Northrend/zone_dragonblight.cpp
+++ b/src/server/scripts/Northrend/zone_dragonblight.cpp
@@ -411,7 +411,7 @@ public:
tree->AI()->Talk(SAY_WALKER_FRIENDLY, player);
tree->DespawnOrUnsummon(1000);
}
- else if (roll == 0) // enemy version
+ else // enemy version
{
tree->AI()->Talk(SAY_WALKER_ENEMY, player);
tree->SetFaction(FACTION_MONSTER);
diff --git a/src/server/scripts/Northrend/zone_grizzly_hills.cpp b/src/server/scripts/Northrend/zone_grizzly_hills.cpp
index f4749ef74f4..6809dce26c2 100644
--- a/src/server/scripts/Northrend/zone_grizzly_hills.cpp
+++ b/src/server/scripts/Northrend/zone_grizzly_hills.cpp
@@ -64,9 +64,9 @@ class npc_emily : public CreatureScript
public:
npc_emily() : CreatureScript("npc_emily") { }
- struct npc_emilyAI : public npc_escortAI
+ struct npc_emilyAI : public EscortAI
{
- npc_emilyAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_emilyAI(Creature* creature) : EscortAI(creature) { }
void JustSummoned(Creature* summoned) override
{
@@ -76,7 +76,7 @@ public:
summoned->AI()->AttackStart(me->GetVictim());
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
@@ -564,6 +564,11 @@ public:
{
npc_venture_co_stragglerAI(Creature* creature) : ScriptedAI(creature) { }
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_CHOP, Seconds(3), Seconds(6));
+ }
+
void Reset() override
{
_playerGUID.Clear();
@@ -602,7 +607,7 @@ public:
case EVENT_CHOP:
if (UpdateVictim())
DoCastVictim(SPELL_CHOP);
- _events.ScheduleEvent(EVENT_CHOP, 10000, 12000);
+ _events.Repeat(Seconds(10), Seconds(12));
break;
default:
break;
@@ -611,7 +616,6 @@ public:
if (!UpdateVictim())
return;
-
DoMeleeAttackIfReady();
}
diff --git a/src/server/scripts/Northrend/zone_howling_fjord.cpp b/src/server/scripts/Northrend/zone_howling_fjord.cpp
index aeb2fa3e59a..e2df8f6ca96 100644
--- a/src/server/scripts/Northrend/zone_howling_fjord.cpp
+++ b/src/server/scripts/Northrend/zone_howling_fjord.cpp
@@ -80,9 +80,9 @@ class npc_apothecary_hanes : public CreatureScript
public:
npc_apothecary_hanes() : CreatureScript("npc_apothecary_hanes") { }
- struct npc_Apothecary_HanesAI : public npc_escortAI
+ struct npc_Apothecary_HanesAI : public EscortAI
{
- npc_Apothecary_HanesAI(Creature* creature) : npc_escortAI(creature)
+ npc_Apothecary_HanesAI(Creature* creature) : EscortAI(creature)
{
Initialize();
}
@@ -133,7 +133,7 @@ public:
if (GetAttack() && UpdateVictim())
DoMeleeAttackIfReady();
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (me->IsInCombat())
return;
@@ -156,7 +156,7 @@ public:
events.Reset();
me->SetFaction(FACTION_ESCORTEE_H_PASSIVE);
me->SetReactState(REACT_AGGRESSIVE);
- ENSURE_AI(npc_escortAI, (me->AI()))->Start(true, true, _player);
+ ENSURE_AI(EscortAI, (me->AI()))->Start(true, true, _player);
break;
case EVENT_TALK_1:
if (Player* player = ObjectAccessor::GetPlayer(*me, _player))
@@ -202,7 +202,7 @@ public:
}
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
@@ -272,9 +272,9 @@ class npc_plaguehound_tracker : public CreatureScript
public:
npc_plaguehound_tracker() : CreatureScript("npc_plaguehound_tracker") { }
- struct npc_plaguehound_trackerAI : public npc_escortAI
+ struct npc_plaguehound_trackerAI : public EscortAI
{
- npc_plaguehound_trackerAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_plaguehound_trackerAI(Creature* creature) : EscortAI(creature) { }
void Reset() override
{
@@ -292,7 +292,7 @@ public:
Start(false, false, summonerGUID);
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
if (waypointId != 26)
return;
diff --git a/src/server/scripts/Northrend/zone_icecrown.cpp b/src/server/scripts/Northrend/zone_icecrown.cpp
index b7f60c8e9d2..ab3b83857d8 100644
--- a/src/server/scripts/Northrend/zone_icecrown.cpp
+++ b/src/server/scripts/Northrend/zone_icecrown.cpp
@@ -433,7 +433,7 @@ public:
void Reset() override
{
- me->setRegeneratingHealth(false);
+ me->SetRegenerateHealth(false);
DoCast(SPELL_THREAT_PULSE);
Talk(BANNER_SAY);
events.ScheduleEvent(EVENT_SPAWN, 3000);
diff --git a/src/server/scripts/Northrend/zone_sholazar_basin.cpp b/src/server/scripts/Northrend/zone_sholazar_basin.cpp
index 118aae0da83..e96c8d2f17d 100644
--- a/src/server/scripts/Northrend/zone_sholazar_basin.cpp
+++ b/src/server/scripts/Northrend/zone_sholazar_basin.cpp
@@ -18,14 +18,18 @@
/* ScriptData
SDName: Sholazar_Basin
SD%Complete: 100
-SDComment: Quest support: 12573, 12621, 12726
+SDComment: Quest support: 12550, 12645, 12688, 12726, 13957
SDCategory: Sholazar_Basin
EndScriptData */
/* ContentData
-npc_vekjik
-avatar_of_freya
+npc_engineer_helice
+npc_jungle_punch_target
+spell_q12620_the_lifewarden_wrath
+spell_q12589_shoot_rjr
npc_haiphoon (Quest: "Song of Wind and Water")
+npc_vics_flying_machine
+spell_shango_tracks
EndContentData */
#include "ScriptMgr.h"
@@ -36,196 +40,11 @@ EndContentData */
#include "ObjectMgr.h"
#include "Player.h"
#include "ScriptedEscortAI.h"
-#include "ScriptedGossip.h"
#include "SpellAuras.h"
#include "SpellScript.h"
-#include "TemporarySummon.h"
#include "Vehicle.h"
/*######
-## 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 Vekjik
-{
- GOSSIP_TEXTID_VEKJIK1 = 13137,
- GOSSIP_TEXTID_VEKJIK2 = 13138,
-
- SAY_TEXTID_VEKJIK1 = 0,
-
- SPELL_FREANZYHEARTS_FURY = 51469,
-
- QUEST_MAKING_PEACE = 12573
-};
-
-class npc_vekjik : public CreatureScript
-{
-public:
- npc_vekjik() : CreatureScript("npc_vekjik") { }
-
- struct npc_vekjikAI : public ScriptedAI
- {
- npc_vekjikAI(Creature* creature) : ScriptedAI(creature) { }
-
- bool GossipHello(Player* player) override
- {
- if (me->IsQuestGiver())
- player->PrepareQuestMenu(me->GetGUID());
-
- if (player->GetQuestStatus(QUEST_MAKING_PEACE) == QUEST_STATUS_INCOMPLETE)
- {
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_VEKJIK_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- SendGossipMenuFor(player, GOSSIP_TEXTID_VEKJIK1, me->GetGUID());
- return true;
- }
-
- SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
- return true;
- }
-
- bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
- {
- uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
- ClearGossipMenuFor(player);
- switch (action)
- {
- case GOSSIP_ACTION_INFO_DEF + 1:
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_VEKJIK_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
- SendGossipMenuFor(player, GOSSIP_TEXTID_VEKJIK2, me->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF + 2:
- CloseGossipMenuFor(player);
- Talk(SAY_TEXTID_VEKJIK1, player);
- player->AreaExploredOrEventHappens(QUEST_MAKING_PEACE);
- DoCast(player, SPELL_FREANZYHEARTS_FURY, false);
- break;
- }
-
- return true;
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_vekjikAI(creature);
- }
-};
-
-/*######
-## 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 Freya
-{
- QUEST_FREYA_PACT = 12621,
-
- SPELL_FREYA_CONVERSATION = 52045,
-
- GOSSIP_TEXTID_AVATAR1 = 13303,
- GOSSIP_TEXTID_AVATAR2 = 13304,
- GOSSIP_TEXTID_AVATAR3 = 13305
-};
-
-class npc_avatar_of_freya : public CreatureScript
-{
-public:
- npc_avatar_of_freya() : CreatureScript("npc_avatar_of_freya") { }
-
- struct npc_avatar_of_freyaAI : public ScriptedAI
- {
- npc_avatar_of_freyaAI(Creature* creature) : ScriptedAI(creature) { }
-
- bool GossipHello(Player* player) override
- {
- if (me->IsQuestGiver())
- player->PrepareQuestMenu(me->GetGUID());
-
- if (player->GetQuestStatus(QUEST_FREYA_PACT) == QUEST_STATUS_INCOMPLETE)
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_AOF1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
-
- player->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXTID_AVATAR1, me->GetGUID());
- return true;
- }
-
- bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
- {
- uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
- ClearGossipMenuFor(player);
- switch (action)
- {
- case GOSSIP_ACTION_INFO_DEF + 1:
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_AOF2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
- player->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXTID_AVATAR2, me->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF + 2:
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_AOF3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
- player->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXTID_AVATAR3, me->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF + 3:
- player->CastSpell(player, SPELL_FREYA_CONVERSATION, true);
- CloseGossipMenuFor(player);
- break;
- }
- return true;
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_avatar_of_freyaAI(creature);
- }
-};
-
-/*######
-## npc_bushwhacker
-######*/
-
-class npc_bushwhacker : public CreatureScript
-{
-public:
- npc_bushwhacker() : CreatureScript("npc_bushwhacker") { }
-
- struct npc_bushwhackerAI : public ScriptedAI
- {
- npc_bushwhackerAI(Creature* creature) : ScriptedAI(creature)
- {
- }
-
- void InitializeAI() override
- {
- if (me->isDead())
- return;
-
- if (TempSummon* summ = me->ToTempSummon())
- if (Unit* summoner = summ->GetSummoner())
- me->GetMotionMaster()->MovePoint(0, summoner->GetPositionX(), summoner->GetPositionY(), summoner->GetPositionZ());
-
- Reset();
- }
-
- void UpdateAI(uint32 /*uiDiff*/) override
- {
- if (!UpdateVictim())
- return;
-
- DoMeleeAttackIfReady();
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_bushwhackerAI(creature);
- }
-};
-
-/*######
## npc_engineer_helice
######*/
@@ -253,9 +72,9 @@ class npc_engineer_helice : public CreatureScript
public:
npc_engineer_helice() : CreatureScript("npc_engineer_helice") { }
- struct npc_engineer_heliceAI : public npc_escortAI
+ struct npc_engineer_heliceAI : public EscortAI
{
- npc_engineer_heliceAI(Creature* creature) : npc_escortAI(creature)
+ npc_engineer_heliceAI(Creature* creature) : EscortAI(creature)
{
Initialize();
}
@@ -267,7 +86,7 @@ public:
uint32 m_uiChatTimer;
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
@@ -322,7 +141,7 @@ public:
void UpdateAI(uint32 uiDiff) override
{
- npc_escortAI::UpdateAI(uiDiff);
+ EscortAI::UpdateAI(uiDiff);
if (HasEscortState(STATE_ESCORT_ESCORTING))
{
@@ -550,96 +369,6 @@ public:
};
/*######
-## npc_adventurous_dwarf
-######*/
-
-#define GOSSIP_OPTION_ORANGE "Can you spare an orange?"
-#define GOSSIP_OPTION_BANANAS "Have a spare bunch of bananas?"
-#define GOSSIP_OPTION_PAPAYA "I could really use a papaya."
-
-enum AdventurousDwarf
-{
- QUEST_12634 = 12634,
-
- ITEM_BANANAS = 38653,
- ITEM_PAPAYA = 38655,
- ITEM_ORANGE = 38656,
-
- SPELL_ADD_ORANGE = 52073,
- SPELL_ADD_BANANAS = 52074,
- SPELL_ADD_PAPAYA = 52076,
-
- GOSSIP_MENU_DWARF = 13307,
-
- SAY_DWARF_OUCH = 0,
- SAY_DWARF_HELP = 1
-};
-
-class npc_adventurous_dwarf : public CreatureScript
-{
-public:
- npc_adventurous_dwarf() : CreatureScript("npc_adventurous_dwarf") { }
-
- struct npc_adventurous_dwarfAI : public ScriptedAI
- {
- npc_adventurous_dwarfAI(Creature* creature) : ScriptedAI(creature)
- {
- Talk(SAY_DWARF_OUCH);
- }
-
- bool GossipHello(Player* player) override
- {
- if (player->GetQuestStatus(QUEST_12634) != QUEST_STATUS_INCOMPLETE)
- return false;
-
- if (player->GetItemCount(ITEM_ORANGE) < 1)
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_OPTION_ORANGE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
-
- if (player->GetItemCount(ITEM_BANANAS) < 2)
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_OPTION_BANANAS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
-
- if (player->GetItemCount(ITEM_PAPAYA) < 1)
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_OPTION_PAPAYA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
-
- player->PlayerTalkClass->SendGossipMenu(GOSSIP_MENU_DWARF, me->GetGUID());
- return true;
- }
-
- bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
- {
- uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
- ClearGossipMenuFor(player);
- uint32 spellId = 0;
-
- switch (action)
- {
- case GOSSIP_ACTION_INFO_DEF + 1:
- spellId = SPELL_ADD_ORANGE;
- break;
- case GOSSIP_ACTION_INFO_DEF + 2:
- spellId = SPELL_ADD_BANANAS;
- break;
- case GOSSIP_ACTION_INFO_DEF + 3:
- spellId = SPELL_ADD_PAPAYA;
- break;
- }
-
- if (spellId)
- player->CastSpell(player, spellId, true);
-
- Talk(SAY_DWARF_HELP);
- me->DespawnOrUnsummon();
- return true;
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_adventurous_dwarfAI(creature);
- }
-};
-
-/*######
## Quest The Lifewarden's Wrath
######*/
@@ -1044,11 +773,7 @@ public:
void AddSC_sholazar_basin()
{
- new npc_vekjik();
- new npc_avatar_of_freya();
- new npc_bushwhacker();
new npc_engineer_helice();
- new npc_adventurous_dwarf();
new npc_jungle_punch_target();
new spell_q12620_the_lifewarden_wrath();
new spell_q12589_shoot_rjr();
diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp
index efe1691d479..c0c22a43696 100644
--- a/src/server/scripts/Northrend/zone_storm_peaks.cpp
+++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp
@@ -48,11 +48,11 @@ class npc_injured_goblin : public CreatureScript
public:
npc_injured_goblin() : CreatureScript("npc_injured_goblin") { }
- struct npc_injured_goblinAI : public npc_escortAI
+ struct npc_injured_goblinAI : public EscortAI
{
- npc_injured_goblinAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_injured_goblinAI(Creature* creature) : EscortAI(creature) { }
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
@@ -82,7 +82,7 @@ public:
void UpdateAI(uint32 uiDiff) override
{
- npc_escortAI::UpdateAI(uiDiff);
+ EscortAI::UpdateAI(uiDiff);
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
@@ -211,7 +211,7 @@ public:
me->CastSpell(me, SPELL_ICE_PRISON, true);
}
- void JustRespawned() override
+ void JustAppeared() override
{
Reset();
}
@@ -346,9 +346,9 @@ class npc_icefang : public CreatureScript
public:
npc_icefang() : CreatureScript("npc_icefang") { }
- struct npc_icefangAI : public npc_escortAI
+ struct npc_icefangAI : public EscortAI
{
- npc_icefangAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_icefangAI(Creature* creature) : EscortAI(creature) { }
void AttackStart(Unit* /*who*/) override { }
void EnterCombat(Unit* /*who*/) override { }
@@ -363,13 +363,12 @@ public:
}
}
- void WaypointReached(uint32 /*waypointId*/) override { }
void JustDied(Unit* /*killer*/) override { }
void OnCharmed(bool /*apply*/) override { }
void UpdateAI(uint32 diff) override
{
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (!UpdateVictim())
return;
@@ -1045,7 +1044,7 @@ class spell_close_rift : public SpellScriptLoader
void HandlePeriodic(AuraEffect const* /* aurEff */)
{
if (++_counter == 5)
- GetTarget()->CastSpell((Unit*)nullptr, SPELL_DESPAWN_RIFT, true);
+ GetTarget()->CastSpell(nullptr, SPELL_DESPAWN_RIFT, true);
}
void Register() override
@@ -1241,7 +1240,7 @@ class spell_low_health_trigger : public SpellScriptLoader
void HandleScript(SpellEffIndex /*effIndex*/)
{
- GetHitUnit()->CastSpell((Unit*)nullptr, GetEffectValue(), true);
+ GetHitUnit()->CastSpell(nullptr, GetEffectValue(), true);
}
void Register() override
@@ -1312,7 +1311,7 @@ class spell_claw_swipe_check : public SpellScriptLoader
}
}
- GetTarget()->CastSpell((Unit*)nullptr, aurEff->GetAmount(), false);
+ GetTarget()->CastSpell(nullptr, aurEff->GetAmount(), false);
}
void Register() override
@@ -1355,7 +1354,7 @@ class spell_fatal_strike : public SpellScriptLoader
return;
}
- GetCaster()->CastSpell((Unit*)nullptr, SPELL_FATAL_STRIKE_DAMAGE, true);
+ GetCaster()->CastSpell(nullptr, SPELL_FATAL_STRIKE_DAMAGE, true);
}
void Register() override
@@ -1422,7 +1421,7 @@ class spell_player_mount_wyrm : public SpellScriptLoader
void HandleDummy(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
- GetTarget()->CastSpell((Unit*)nullptr, SPELL_FIGHT_WYRM, true);
+ GetTarget()->CastSpell(nullptr, SPELL_FIGHT_WYRM, true);
}
void Register() override
diff --git a/src/server/scripts/Northrend/zone_zuldrak.cpp b/src/server/scripts/Northrend/zone_zuldrak.cpp
index 607e6845157..30ae441d7ce 100644
--- a/src/server/scripts/Northrend/zone_zuldrak.cpp
+++ b/src/server/scripts/Northrend/zone_zuldrak.cpp
@@ -924,7 +924,7 @@ public:
me->CastSpell(me, STORM_VISUAL, true);
}
- void JustRespawned() override
+ void JustAppeared() override
{
Reset();
}
diff --git a/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_talon_king_ikiss.cpp b/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_talon_king_ikiss.cpp
index a6340227270..1573fb3bcf7 100644
--- a/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_talon_king_ikiss.cpp
+++ b/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_talon_king_ikiss.cpp
@@ -178,6 +178,9 @@ class spell_talon_king_ikiss_blink : public SpellScriptLoader
void FilterTargets(std::list<WorldObject*>& targets)
{
+ if (targets.empty())
+ return;
+
WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
targets.clear();
targets.push_back(target);
diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp
index c12dd178729..945edfe3772 100644
--- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp
+++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp
@@ -57,9 +57,9 @@ class boss_ambassador_hellmaw : public CreatureScript
public:
boss_ambassador_hellmaw() : CreatureScript("boss_ambassador_hellmaw") { }
- struct boss_ambassador_hellmawAI : public npc_escortAI
+ struct boss_ambassador_hellmawAI : public EscortAI
{
- boss_ambassador_hellmawAI(Creature* creature) : npc_escortAI(creature)
+ boss_ambassador_hellmawAI(Creature* creature) : EscortAI(creature)
{
_instance = creature->GetInstanceScript();
_intro = false;
@@ -86,11 +86,7 @@ class boss_ambassador_hellmaw : public CreatureScript
if (me->HasAura(SPELL_BANISH))
return;
- npc_escortAI::MoveInLineOfSight(who);
- }
-
- void WaypointReached(uint32 /*waypointId*/) override
- {
+ EscortAI::MoveInLineOfSight(who);
}
void DoAction(int32 actionId) override
diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp
index e5458ac1b10..04cc23136d9 100644
--- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp
+++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp
@@ -16,16 +16,15 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/*
-Name: Boss_Blackheart_the_Inciter
-%Complete: 75
-Comment: Incite Chaos not functional since core lacks Mind Control support
-Category: Auchindoun, Shadow Labyrinth
-*/
-
-#include "ScriptMgr.h"
+#include "InstanceScript.h"
+#include "Map.h"
#include "ObjectAccessor.h"
+#include "PassiveAI.h"
+#include "Player.h"
+#include "PlayerAI.h"
+#include "ScriptMgr.h"
#include "ScriptedCreature.h"
+#include "SpellScript.h"
#include "shadow_labyrinth.h"
enum BlackheartTheInciter
@@ -56,94 +55,178 @@ enum Events
EVENT_WAR_STOMP = 3
};
-class boss_blackheart_the_inciter : public CreatureScript
+class BlackheartCharmedPlayerAI : public SimpleCharmedPlayerAI
{
- public:
- boss_blackheart_the_inciter() : CreatureScript("boss_blackheart_the_inciter") { }
-
- struct boss_blackheart_the_inciterAI : public BossAI
+ using SimpleCharmedPlayerAI::SimpleCharmedPlayerAI;
+ void OnCharmed(bool apply) override
+ {
+ SimpleCharmedPlayerAI::OnCharmed(apply);
+ if (!me->GetMap()->IsDungeon())
+ return;
+ if (Creature* blackheart = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(DATA_BLACKHEART_THE_INCITER)))
{
- boss_blackheart_the_inciterAI(Creature* creature) : BossAI(creature, DATA_BLACKHEART_THE_INCITER) { }
-
- void Reset() override
- {
- _Reset();
- }
-
- void EnterCombat(Unit* /*who*/) override
- {
- _EnterCombat();
- events.ScheduleEvent(EVENT_INCITE_CHAOS, 20000);
- events.ScheduleEvent(EVENT_CHARGE_ATTACK, 5000);
- events.ScheduleEvent(EVENT_WAR_STOMP, 15000);
-
- Talk(SAY_AGGRO);
- }
-
- void KilledUnit(Unit* who) override
- {
- if (who->GetTypeId() == TYPEID_PLAYER)
- Talk(SAY_SLAY);
- }
+ blackheart->AI()->SetData(0, apply);
+ blackheart->GetThreatManager().AddThreat(me, 0.0f);
+ }
+ }
+};
- void JustDied(Unit* /*killer*/) override
+struct boss_blackheart_the_inciter : public BossAI
+{
+ boss_blackheart_the_inciter(Creature* creature) : BossAI(creature, DATA_BLACKHEART_THE_INCITER) { }
+
+ void Reset() override
+ {
+ me->SetReactState(REACT_AGGRESSIVE);
+ _Reset();
+ }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _EnterCombat();
+ events.ScheduleEvent(EVENT_INCITE_CHAOS, 20000);
+ events.ScheduleEvent(EVENT_CHARGE_ATTACK, 5000);
+ events.ScheduleEvent(EVENT_WAR_STOMP, 15000);
+
+ Talk(SAY_AGGRO);
+ }
+
+ void KilledUnit(Unit* who) override
+ {
+ if (who->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SLAY);
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ Talk(SAY_DEATH);
+ }
+
+ uint8 charmCount = 0;
+ void SetData(uint32 /*index*/, uint32 data) override
+ {
+ if (data)
+ ++charmCount;
+ else
+ {
+ if (!charmCount)
+ EnterEvadeMode(EVADE_REASON_OTHER); // sanity check
+ --charmCount;
+ }
+ if (charmCount)
+ me->SetReactState(REACT_PASSIVE);
+ else
+ me->SetReactState(REACT_AGGRESSIVE);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ events.Update(diff);
+ if (me->HasReactState(REACT_PASSIVE) || !UpdateVictim())
+ return;
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- _JustDied();
- Talk(SAY_DEATH);
+ case EVENT_INCITE_CHAOS:
+ {
+ if (me->GetThreatManager().GetThreatListSize() > 1)
+ {
+ ResetThreatList();
+ DoCast(me, SPELL_INCITE_CHAOS);
+ }
+ events.ScheduleEvent(EVENT_INCITE_CHAOS, 40000);
+ break;
+ }
+ case EVENT_CHARGE_ATTACK:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ DoCast(target, SPELL_CHARGE);
+ events.ScheduleEvent(EVENT_CHARGE, urand(15000, 25000));
+ break;
+ case EVENT_WAR_STOMP:
+ DoCast(me, SPELL_WAR_STOMP);
+ events.ScheduleEvent(EVENT_WAR_STOMP, urand(18000, 24000));
+ break;
}
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
-
- events.Update(diff);
+ if (me->HasReactState(REACT_PASSIVE) || me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ DoMeleeAttackIfReady();
+ }
+};
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
+struct boss_blackheart_the_inciter_mc_dummy : public NullCreatureAI
+{
+ using NullCreatureAI::NullCreatureAI;
+ void InitializeAI() override { me->SetReactState(REACT_PASSIVE); }
+ static const uint32 FIRST_DUMMY = NPC_BLACKHEART_DUMMY1, LAST_DUMMY = NPC_BLACKHEART_DUMMY5;
+ void IsSummonedBy(Unit* who) override
+ {
+ me->CastSpell(who, SPELL_INCITE_CHAOS_B, true);
+
+ // ensure everyone is in combat with everyone
+ if (auto* dummies = GetBlackheartDummies(me->GetInstanceScript()))
+ for (ObjectGuid const& guid : *dummies)
+ if (Creature* trigger = ObjectAccessor::GetCreature(*me, guid))
+ if (me->GetEntry() != trigger->GetEntry())
{
- case EVENT_INCITE_CHAOS:
+ me->GetThreatManager().AddThreat(trigger, 0.0f);
+ trigger->GetThreatManager().AddThreat(who, 0.0f);
+ for (Unit* other : trigger->m_Controlled)
{
- DoCast(me, SPELL_INCITE_CHAOS);
-
- for (ThreatReference const* ref : me->GetThreatManager().GetUnsortedThreatList())
- if (ref->GetVictim()->GetTypeId() == TYPEID_PLAYER)
- me->CastSpell(ref->GetVictim(), SPELL_INCITE_CHAOS_B, true);
-
- ResetThreatList();
- events.ScheduleEvent(EVENT_INCITE_CHAOS, 40000);
- break;
+ me->GetThreatManager().AddThreat(other, 0.0f);
+ other->GetThreatManager().AddThreat(who, 0.0f);
}
- case EVENT_CHARGE_ATTACK:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, SPELL_CHARGE);
- events.ScheduleEvent(EVENT_CHARGE, urand(15000, 25000));
- break;
- case EVENT_WAR_STOMP:
- DoCast(me, SPELL_WAR_STOMP);
- events.ScheduleEvent(EVENT_WAR_STOMP, urand(18000, 24000));
- break;
}
+ }
+ void UpdateAI(uint32 /*diff*/) override
+ {
+ if (me->m_Controlled.empty())
+ me->DespawnOrUnsummon();
+ }
+ PlayerAI* GetAIForCharmedPlayer(Player* player) override
+ {
+ return new BlackheartCharmedPlayerAI(player);
+ }
+};
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- }
-
- DoMeleeAttackIfReady();
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
+class spell_blackheart_incite_chaos : public SpellScript
+{
+ PrepareSpellScript(spell_blackheart_incite_chaos);
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_INCITE_CHAOS_B });
+ }
+
+ static const uint8 NUM_INCITE_SPELLS = 5;
+ static const uint32 INCITE_SPELLS[NUM_INCITE_SPELLS];
+ uint8 i=0;
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
{
- return GetShadowLabyrinthAI<boss_blackheart_the_inciterAI>(creature);
+ target->CastSpell(nullptr, INCITE_SPELLS[i], true);
+ i = (i + 1) % NUM_INCITE_SPELLS;
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_blackheart_incite_chaos::HandleDummy, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
+const uint32 spell_blackheart_incite_chaos::INCITE_SPELLS[spell_blackheart_incite_chaos::NUM_INCITE_SPELLS] = { 33677,33680,33681,33682,33683 };
void AddSC_boss_blackheart_the_inciter()
{
- new boss_blackheart_the_inciter();
+ RegisterCreatureAIWithFactory(boss_blackheart_the_inciter, GetShadowLabyrinthAI);
+ RegisterCreatureAIWithFactory(boss_blackheart_the_inciter_mc_dummy, GetShadowLabyrinthAI);
+ RegisterSpellScript(spell_blackheart_incite_chaos);
}
diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp
index edaab7cd9cb..1d415bed072 100644
--- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp
+++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp
@@ -185,7 +185,7 @@ class spell_murmur_sonic_boom : public SpellScriptLoader
void HandleEffect(SpellEffIndex /*effIndex*/)
{
- GetCaster()->CastSpell((Unit*)nullptr, SPELL_SONIC_BOOM_EFFECT, true);
+ GetCaster()->CastSpell(nullptr, SPELL_SONIC_BOOM_EFFECT, true);
}
void Register() override
diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp
index c5ddb8e6b50..709b3569134 100644
--- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp
+++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp
@@ -53,6 +53,16 @@ class instance_shadow_labyrinth : public InstanceMapScript
case NPC_AMBASSADOR_HELLMAW:
AmbassadorHellmawGUID = creature->GetGUID();
break;
+ case NPC_BLACKHEART:
+ BlackheartGUID = creature->GetGUID();
+ break;
+ case NPC_BLACKHEART_DUMMY1:
+ case NPC_BLACKHEART_DUMMY2:
+ case NPC_BLACKHEART_DUMMY3:
+ case NPC_BLACKHEART_DUMMY4:
+ case NPC_BLACKHEART_DUMMY5:
+ BlackheartDummyGUIDs.insert(creature->GetGUID());
+ break;
case NPC_GRANDMASTER_VORPIL:
GrandmasterVorpilGUID = creature->GetGUID();
break;
@@ -69,6 +79,22 @@ class instance_shadow_labyrinth : public InstanceMapScript
}
}
+ void OnCreatureRemove(Creature* creature) override
+ {
+ switch (creature->GetEntry())
+ {
+ case NPC_BLACKHEART_DUMMY1:
+ case NPC_BLACKHEART_DUMMY2:
+ case NPC_BLACKHEART_DUMMY3:
+ case NPC_BLACKHEART_DUMMY4:
+ case NPC_BLACKHEART_DUMMY5:
+ BlackheartDummyGUIDs.erase(creature->GetGUID());
+ break;
+ default:
+ break;
+ }
+ }
+
void OnGameObjectCreate(GameObject* go) override
{
switch (go->GetEntry())
@@ -128,6 +154,8 @@ class instance_shadow_labyrinth : public InstanceMapScript
{
switch (type)
{
+ case DATA_BLACKHEART_THE_INCITER:
+ return BlackheartGUID;
case DATA_GRANDMASTER_VORPIL:
return GrandmasterVorpilGUID;
default:
@@ -136,8 +164,12 @@ class instance_shadow_labyrinth : public InstanceMapScript
return ObjectGuid::Empty;
}
+ GuidUnorderedSet const& GetBlackheartDummies() const { return BlackheartDummyGUIDs; }
+
protected:
ObjectGuid AmbassadorHellmawGUID;
+ ObjectGuid BlackheartGUID;
+ GuidUnorderedSet BlackheartDummyGUIDs;
ObjectGuid GrandmasterVorpilGUID;
uint32 FelOverseerCount;
};
@@ -148,6 +180,14 @@ class instance_shadow_labyrinth : public InstanceMapScript
}
};
+GuidUnorderedSet const* GetBlackheartDummies(InstanceScript const* s)
+{
+ if (auto* script = dynamic_cast<instance_shadow_labyrinth::instance_shadow_labyrinth_InstanceMapScript const*>(s))
+ return &script->GetBlackheartDummies();
+ return nullptr;
+
+}
+
void AddSC_instance_shadow_labyrinth()
{
new instance_shadow_labyrinth();
diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.h b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.h
index 0c7e7b5afca..262a7b9c494 100644
--- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.h
+++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.h
@@ -19,6 +19,7 @@
#define SHADOW_LABYRINTH_H_
#include "CreatureAIImpl.h"
+#include "ObjectGuid.h"
#define SLScriptName "instance_shadow_labyrinth"
#define DataHeader "SL"
@@ -40,6 +41,12 @@ enum SLDataTypes
enum SLCreatureIds
{
NPC_AMBASSADOR_HELLMAW = 18731,
+ NPC_BLACKHEART = 18667,
+ NPC_BLACKHEART_DUMMY1 = 19300,
+ NPC_BLACKHEART_DUMMY2 = 19301,
+ NPC_BLACKHEART_DUMMY3 = 19302,
+ NPC_BLACKHEART_DUMMY4 = 19303,
+ NPC_BLACKHEART_DUMMY5 = 19304,
NPC_GRANDMASTER_VORPIL = 18732,
NPC_FEL_OVERSEER = 18796
};
@@ -56,6 +63,8 @@ enum SLMisc
ACTION_AMBASSADOR_HELLMAW_BANISH = 2,
};
+GuidUnorderedSet const* GetBlackheartDummies(InstanceScript const* s);
+
template <class AI, class T>
inline AI* GetShadowLabyrinthAI(T* obj)
{
diff --git a/src/server/scripts/Outland/BlackTemple/black_temple.cpp b/src/server/scripts/Outland/BlackTemple/black_temple.cpp
index 08b00caa519..693d2be970d 100644
--- a/src/server/scripts/Outland/BlackTemple/black_temple.cpp
+++ b/src/server/scripts/Outland/BlackTemple/black_temple.cpp
@@ -57,274 +57,226 @@ enum Misc
GROUP_OUT_OF_COMBAT = 1
};
-// ########################################################
-// Wrathbone Flayer
-// ########################################################
-
-class npc_wrathbone_flayer : public CreatureScript
+struct npc_wrathbone_flayer : public ScriptedAI
{
-public:
- npc_wrathbone_flayer() : CreatureScript("npc_wrathbone_flayer") { }
+ npc_wrathbone_flayer(Creature* creature) : ScriptedAI(creature)
+ {
+ Initialize();
+ _instance = creature->GetInstanceScript();
+ }
- struct npc_wrathbone_flayerAI : public ScriptedAI
+ void Initialize()
{
- npc_wrathbone_flayerAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- _instance = creature->GetInstanceScript();
- }
+ _enteredCombat = false;
+ }
- void Initialize()
- {
- _enteredCombat = false;
- }
+ void Reset() override
+ {
+ _events.ScheduleEvent(EVENT_GET_CHANNELERS, 3000);
+ Initialize();
+ _bloodmageList.clear();
+ _deathshaperList.clear();
+ }
- void Reset() override
- {
- _events.ScheduleEvent(EVENT_GET_CHANNELERS, 3000);
- Initialize();
- _bloodmageList.clear();
- _deathshaperList.clear();
- }
+ void JustDied(Unit* /*killer*/) override { }
- void JustDied(Unit* /*killer*/) override { }
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_CLEAVE, 5000);
+ _events.ScheduleEvent(EVENT_IGNORED, 7000);
+ _enteredCombat = true;
+ }
- void EnterCombat(Unit* /*who*/) override
+ void UpdateAI(uint32 diff) override
+ {
+ if (!_enteredCombat)
{
- _events.ScheduleEvent(EVENT_CLEAVE, 5000);
- _events.ScheduleEvent(EVENT_IGNORED, 7000);
- _enteredCombat = true;
- }
+ _events.Update(diff);
- void UpdateAI(uint32 diff) override
- {
- if (!_enteredCombat)
+ while (uint32 eventId = _events.ExecuteEvent())
{
- _events.Update(diff);
-
- while (uint32 eventId = _events.ExecuteEvent())
+ switch (eventId)
{
- switch (eventId)
+ case EVENT_GET_CHANNELERS:
{
- case EVENT_GET_CHANNELERS:
- {
- std::list<Creature*> BloodMageList;
- me->GetCreatureListWithEntryInGrid(BloodMageList, NPC_BLOOD_MAGE, 15.0f);
-
- if (!BloodMageList.empty())
- for (std::list<Creature*>::const_iterator itr = BloodMageList.begin(); itr != BloodMageList.end(); ++itr)
- {
- _bloodmageList.push_back((*itr)->GetGUID());
- if ((*itr)->isDead())
- (*itr)->Respawn();
- }
-
- std::list<Creature*> DeathShaperList;
- me->GetCreatureListWithEntryInGrid(DeathShaperList, NPC_DEATHSHAPER, 15.0f);
-
- if (!DeathShaperList.empty())
- for (std::list<Creature*>::const_iterator itr = DeathShaperList.begin(); itr != DeathShaperList.end(); ++itr)
- {
- _deathshaperList.push_back((*itr)->GetGUID());
- if ((*itr)->isDead())
- (*itr)->Respawn();
- }
-
- _events.ScheduleEvent(EVENT_SET_CHANNELERS, 3000);
-
- break;
- }
- case EVENT_SET_CHANNELERS:
- {
- for (ObjectGuid guid : _bloodmageList)
- if (Creature* bloodmage = ObjectAccessor::GetCreature(*me, guid))
- bloodmage->CastSpell((Unit*)nullptr, SPELL_SUMMON_CHANNEL);
-
- for (ObjectGuid guid : _deathshaperList)
- if (Creature* deathshaper = ObjectAccessor::GetCreature(*me, guid))
- deathshaper->CastSpell((Unit*)nullptr, SPELL_SUMMON_CHANNEL);
-
- _events.ScheduleEvent(EVENT_SET_CHANNELERS, 12000);
-
- break;
- }
- default:
- break;
+ std::list<Creature*> BloodMageList;
+ me->GetCreatureListWithEntryInGrid(BloodMageList, NPC_BLOOD_MAGE, 15.0f);
+
+ if (!BloodMageList.empty())
+ for (std::list<Creature*>::const_iterator itr = BloodMageList.begin(); itr != BloodMageList.end(); ++itr)
+ {
+ _bloodmageList.push_back((*itr)->GetGUID());
+ if ((*itr)->isDead())
+ (*itr)->Respawn();
+ }
+
+ std::list<Creature*> DeathShaperList;
+ me->GetCreatureListWithEntryInGrid(DeathShaperList, NPC_DEATHSHAPER, 15.0f);
+
+ if (!DeathShaperList.empty())
+ for (std::list<Creature*>::const_iterator itr = DeathShaperList.begin(); itr != DeathShaperList.end(); ++itr)
+ {
+ _deathshaperList.push_back((*itr)->GetGUID());
+ if ((*itr)->isDead())
+ (*itr)->Respawn();
+ }
+
+ _events.ScheduleEvent(EVENT_SET_CHANNELERS, 3000);
+
+ break;
}
- }
- }
+ case EVENT_SET_CHANNELERS:
+ {
+ for (ObjectGuid guid : _bloodmageList)
+ if (Creature* bloodmage = ObjectAccessor::GetCreature(*me, guid))
+ bloodmage->CastSpell(nullptr, SPELL_SUMMON_CHANNEL);
- if (!UpdateVictim())
- return;
+ for (ObjectGuid guid : _deathshaperList)
+ if (Creature* deathshaper = ObjectAccessor::GetCreature(*me, guid))
+ deathshaper->CastSpell(nullptr, SPELL_SUMMON_CHANNEL);
- _events.Update(diff);
+ _events.ScheduleEvent(EVENT_SET_CHANNELERS, 12000);
- while (uint32 eventId = _events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_CLEAVE:
- DoCastVictim(SPELL_CLEAVE);
- _events.ScheduleEvent(EVENT_CLEAVE, urand (1000, 2000));
- break;
- case EVENT_IGNORED:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, SPELL_IGNORED);
- _events.ScheduleEvent(EVENT_IGNORED, 10000);
break;
+ }
default:
break;
}
}
- DoMeleeAttackIfReady();
}
- private:
- InstanceScript* _instance;
- EventMap _events;
- GuidList _bloodmageList;
- GuidList _deathshaperList;
- bool _enteredCombat;
- };
+ if (!UpdateVictim())
+ return;
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<npc_wrathbone_flayerAI>(creature);
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_CLEAVE:
+ DoCastVictim(SPELL_CLEAVE);
+ _events.ScheduleEvent(EVENT_CLEAVE, urand(1000, 2000));
+ break;
+ case EVENT_IGNORED:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ DoCast(target, SPELL_IGNORED);
+ _events.ScheduleEvent(EVENT_IGNORED, 10000);
+ break;
+ default:
+ break;
+ }
+ }
+ DoMeleeAttackIfReady();
}
+
+private:
+ InstanceScript* _instance;
+ EventMap _events;
+ GuidList _bloodmageList;
+ GuidList _deathshaperList;
+ bool _enteredCombat;
};
-class npc_angered_soul_fragment : public CreatureScript
+struct npc_angered_soul_fragment : public ScriptedAI
{
-public:
- npc_angered_soul_fragment() : CreatureScript("npc_angered_soul_fragment") { }
+ npc_angered_soul_fragment(Creature* creature) : ScriptedAI(creature) { }
- struct npc_angered_soul_fragmentAI : public ScriptedAI
+ void Reset() override
{
- npc_angered_soul_fragmentAI(Creature* creature) : ScriptedAI(creature) { }
+ _scheduler.CancelAll();
- void Reset() override
+ _scheduler.Schedule(Seconds(1), GROUP_OUT_OF_COMBAT, [this](TaskContext invi)
{
- _scheduler.CancelAll();
+ DoCastSelf(SPELL_GREATER_INVISIBILITY);
- _scheduler.Schedule(Seconds(1), GROUP_OUT_OF_COMBAT, [this](TaskContext invi)
+ /* Workaround - On Retail creature appear and "vanish" again periodically, but i cant find packets
+ with UPDATE_AURA on sniffs about it */
+ _scheduler.Schedule(Seconds(5), Seconds(10), GROUP_OUT_OF_COMBAT, [this](TaskContext /*context*/)
{
- DoCastSelf(SPELL_GREATER_INVISIBILITY);
-
- /* Workaround - On Retail creature appear and "vanish" again periodically, but i cant find packets
- with UPDATE_AURA on sniffs about it */
- _scheduler.Schedule(Seconds(5), Seconds(10), GROUP_OUT_OF_COMBAT, [this](TaskContext /*context*/)
- {
- me->RemoveAurasDueToSpell(SPELL_GREATER_INVISIBILITY);
- });
-
- invi.Repeat(Seconds(15), Seconds(25));
+ me->RemoveAurasDueToSpell(SPELL_GREATER_INVISIBILITY);
});
- }
- void EnterCombat(Unit* /*who*/) override
- {
- me->RemoveAurasDueToSpell(SPELL_GREATER_INVISIBILITY);
+ invi.Repeat(Seconds(15), Seconds(25));
+ });
+ }
- _scheduler.CancelGroup(GROUP_OUT_OF_COMBAT);
- _scheduler.Schedule(Seconds(1), [this](TaskContext anger)
- {
- Unit* target = me->GetVictim();
- if (target && me->IsWithinMeleeRange(target))
- DoCastSelf(SPELL_ANGER);
- else
- anger.Repeat(Seconds(1));
- });
- }
+ void EnterCombat(Unit* /*who*/) override
+ {
+ me->RemoveAurasDueToSpell(SPELL_GREATER_INVISIBILITY);
- void UpdateAI(uint32 diff) override
+ _scheduler.CancelGroup(GROUP_OUT_OF_COMBAT);
+ _scheduler.Schedule(Seconds(1), [this](TaskContext anger)
{
- _scheduler.Update(diff);
-
- if (!UpdateVictim())
- return;
+ Unit* target = me->GetVictim();
+ if (target && me->IsWithinMeleeRange(target))
+ DoCastSelf(SPELL_ANGER);
+ else
+ anger.Repeat(Seconds(1));
+ });
+ }
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ void UpdateAI(uint32 diff) override
+ {
+ _scheduler.Update(diff);
- DoMeleeAttackIfReady();
- }
+ if (!UpdateVictim())
+ return;
- private:
- TaskScheduler _scheduler;
- };
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<npc_angered_soul_fragmentAI>(creature);
+ DoMeleeAttackIfReady();
}
+
+private:
+ TaskScheduler _scheduler;
};
// 41986 - Anger
-class spell_soul_fragment_anger : public SpellScriptLoader
+class spell_soul_fragment_anger : public SpellScript
{
- public:
- spell_soul_fragment_anger() : SpellScriptLoader("spell_soul_fragment_anger") { }
-
- class spell_soul_fragment_anger_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_soul_fragment_anger_SpellScript);
+ PrepareSpellScript(spell_soul_fragment_anger);
- void HandleKill()
- {
- if (Creature* caster = GetCaster()->ToCreature())
- caster->DespawnOrUnsummon(Milliseconds(200));
- }
-
- void Register() override
- {
- AfterCast += SpellCastFn(spell_soul_fragment_anger_SpellScript::HandleKill);
- }
- };
+ void HandleKill()
+ {
+ if (Creature* caster = GetCaster()->ToCreature())
+ caster->DespawnOrUnsummon(Milliseconds(200));
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_soul_fragment_anger_SpellScript();
- }
+ void Register() override
+ {
+ AfterCast += SpellCastFn(spell_soul_fragment_anger::HandleKill);
+ }
};
// 39645 - Shadow Inferno
-class spell_illidari_nightlord_shadow_inferno : public SpellScriptLoader
+class spell_illidari_nightlord_shadow_inferno : public AuraScript
{
- public:
- spell_illidari_nightlord_shadow_inferno() : SpellScriptLoader("spell_illidari_nightlord_shadow_inferno") { }
-
- class spell_illidari_nightlord_shadow_inferno_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_illidari_nightlord_shadow_inferno_AuraScript);
+ PrepareAuraScript(spell_illidari_nightlord_shadow_inferno);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_SHADOW_INFERNO_DAMAGE });
- }
-
- void OnPeriodic(AuraEffect const* aurEffect)
- {
- PreventDefaultAction();
- int32 bp = aurEffect->GetTickNumber() * aurEffect->GetAmount();
- GetUnitOwner()->CastCustomSpell(SPELL_SHADOW_INFERNO_DAMAGE, SPELLVALUE_BASE_POINT0, bp, GetUnitOwner(), true);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SHADOW_INFERNO_DAMAGE });
+ }
- void Register() override
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidari_nightlord_shadow_inferno_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
- }
- };
+ void OnPeriodic(AuraEffect const* aurEffect)
+ {
+ PreventDefaultAction();
+ int32 bp = aurEffect->GetTickNumber() * aurEffect->GetAmount();
+ GetUnitOwner()->CastCustomSpell(SPELL_SHADOW_INFERNO_DAMAGE, SPELLVALUE_BASE_POINT0, bp, GetUnitOwner(), true);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_illidari_nightlord_shadow_inferno_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidari_nightlord_shadow_inferno::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
};
void AddSC_black_temple()
{
- new npc_wrathbone_flayer();
- new npc_angered_soul_fragment();
- new spell_soul_fragment_anger();
- new spell_illidari_nightlord_shadow_inferno();
+ RegisterBlackTempleCreatureAI(npc_wrathbone_flayer);
+ RegisterBlackTempleCreatureAI(npc_angered_soul_fragment);
+ RegisterSpellScript(spell_soul_fragment_anger);
+ RegisterAuraScript(spell_illidari_nightlord_shadow_inferno);
}
diff --git a/src/server/scripts/Outland/BlackTemple/black_temple.h b/src/server/scripts/Outland/BlackTemple/black_temple.h
index bdade01ab33..02b587d374f 100644
--- a/src/server/scripts/Outland/BlackTemple/black_temple.h
+++ b/src/server/scripts/Outland/BlackTemple/black_temple.h
@@ -40,25 +40,22 @@ enum BTDataTypes
// Additional Data
DATA_AKAMA_SHADE = 9,
-
DATA_AKAMA = 10,
DATA_MAIEV = 11,
DATA_GO_ILLIDAN_GATE = 12,
DATA_BLACK_TEMPLE_TRIGGER = 13,
-
DATA_GATHIOS_THE_SHATTERER = 14,
DATA_HIGH_NETHERMANCER_ZEREVOR = 15,
DATA_LADY_MALANDE = 16,
DATA_VERAS_DARKSHADOW = 17,
DATA_BLOOD_ELF_COUNCIL_VOICE = 18,
-
DATA_GO_DEN_OF_MORTAL_DOOR = 19,
-
DATA_ESSENCE_OF_SUFFERING = 20,
DATA_ESSENCE_OF_DESIRE = 21,
DATA_ESSENCE_OF_ANGER = 22,
-
DATA_ILLIDAN_MUSIC_CONTROLLER = 23,
+ DATA_TERON_GOREFIEND_INTRO = 24,
+ DATA_AKAMA_ILLIDAN_INTRO = 25
};
enum TriggerEmotes
@@ -108,7 +105,8 @@ enum BTCreatureIds
NPC_ILLIDARI_ELITE = 23226,
NPC_GLAIVE_TARGET = 23448,
NPC_GLAIVE_WORLD_TRIGGER = 22515,
- NPC_DEMON_FIRE = 23069
+ NPC_DEMON_FIRE = 23069,
+ NPC_PARASITIC_SHADOWFIEND = 23498
};
enum BTGameObjectIds
@@ -146,4 +144,6 @@ inline AI* GetBlackTempleAI(T* obj)
return GetInstanceAI<AI>(obj, BTScriptName);
}
+#define RegisterBlackTempleCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetBlackTempleAI)
+
#endif // BLACK_TEMPLE_H_
diff --git a/src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp b/src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp
index 037eaa82d99..7e743b1c62e 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp
@@ -89,322 +89,279 @@ enum Events
EVENT_CHARGE_PLAYER
};
-class boss_gurtogg_bloodboil : public CreatureScript
+
+struct boss_gurtogg_bloodboil : public BossAI
{
-public:
- boss_gurtogg_bloodboil() : CreatureScript("boss_gurtogg_bloodboil") { }
+ boss_gurtogg_bloodboil(Creature* creature) : BossAI(creature, DATA_GURTOGG_BLOODBOIL)
+ {
+ Initialize();
+ }
- struct boss_gurtogg_bloodboilAI : public BossAI
+ void Reset() override
{
- boss_gurtogg_bloodboilAI(Creature* creature) : BossAI(creature, DATA_GURTOGG_BLOODBOIL)
- {
- Initialize();
- }
+ _Reset();
+ Initialize();
+ events.SetPhase(PHASE_1);
+ me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
+ me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false);
+ }
- void Reset() override
- {
- _Reset();
- Initialize();
- events.SetPhase(PHASE_1);
- me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
- me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false);
- }
+ void Initialize()
+ {
+ _oldThreat = 0.0f;
+ _oldTargetGUID.Clear();
+ _targetGUID.Clear();
+ }
- void Initialize()
- {
- _oldThreat = 0.0f;
- _oldTargetGUID.Clear();
- _targetGUID.Clear();
- }
+ bool CanAIAttack(Unit const* who) const override
+ {
+ return BossAI::CanAIAttack(who) && !who->HasAura(SPELL_BEWILDERING_STRIKE);
+ }
- bool CanAIAttack(Unit const* who) const override
- {
- return BossAI::CanAIAttack(who) && !who->HasAura(SPELL_BEWILDERING_STRIKE);
- }
+ void AttackStart(Unit* who) override
+ {
+ if (!CanAIAttack(who))
+ return;
- void AttackStart(Unit* who) override
- {
- if (!CanAIAttack(who))
- return;
+ BossAI::AttackStart(who);
+ }
- BossAI::AttackStart(who);
- }
+ void EnterCombat(Unit* /*who*/) override
+ {
+ Talk(SAY_AGGRO);
+ _EnterCombat();
+ events.ScheduleEvent(EVENT_BERSERK, Minutes(10));
+ events.ScheduleEvent(EVENT_CHANGE_PHASE, Seconds(60));
+ ScheduleEvents();
+ }
- void EnterCombat(Unit* /*who*/) override
- {
- Talk(SAY_AGGRO);
- _EnterCombat();
- events.ScheduleEvent(EVENT_BERSERK, Minutes(10));
- events.ScheduleEvent(EVENT_CHANGE_PHASE, Seconds(60));
- ScheduleEvents();
- }
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ _DespawnAtEvade();
+ }
- void EnterEvadeMode(EvadeReason /*why*/) override
+ void ScheduleEvents()
+ {
+ if (events.IsInPhase(PHASE_1))
{
- _DespawnAtEvade();
+ events.ScheduleEvent(EVENT_BLOODBOIL, Seconds(10), GROUP_PHASE_1, PHASE_1);
+ events.ScheduleEvent(EVENT_ARCING_SMASH, Seconds(10), GROUP_PHASE_1, PHASE_1);
+ events.ScheduleEvent(EVENT_FEL_ACID_BREATH, Seconds(25), GROUP_PHASE_1, PHASE_1);
+ events.ScheduleEvent(EVENT_EJECT, Seconds(35), GROUP_PHASE_1, PHASE_1);
+ events.ScheduleEvent(EVENT_BEWILDERING_STRIKE, Seconds(47), GROUP_PHASE_1, PHASE_1);
}
-
- void ScheduleEvents()
+ else if (events.IsInPhase(PHASE_2))
{
- if (events.IsInPhase(PHASE_1))
- {
- events.ScheduleEvent(EVENT_BLOODBOIL, Seconds(10), GROUP_PHASE_1, PHASE_1);
- events.ScheduleEvent(EVENT_ARCING_SMASH, Seconds(10), GROUP_PHASE_1, PHASE_1);
- events.ScheduleEvent(EVENT_FEL_ACID_BREATH, Seconds(25), GROUP_PHASE_1, PHASE_1);
- events.ScheduleEvent(EVENT_EJECT, Seconds(35), GROUP_PHASE_1, PHASE_1);
- events.ScheduleEvent(EVENT_BEWILDERING_STRIKE, Seconds(47), GROUP_PHASE_1, PHASE_1);
- }
- else if (events.IsInPhase(PHASE_2))
- {
- events.ScheduleEvent(EVENT_START_PHASE_2, Milliseconds(100), GROUP_PHASE_2, PHASE_2);
- events.ScheduleEvent(EVENT_EJECT_2, Seconds(14), GROUP_PHASE_2, PHASE_2);
- events.ScheduleEvent(EVENT_FEL_ACID_BREATH_2, Seconds(16), GROUP_PHASE_2, PHASE_2);
- events.ScheduleEvent(EVENT_ARCING_SMASH_2, Seconds(8), GROUP_PHASE_2, PHASE_2);
- }
+ events.ScheduleEvent(EVENT_START_PHASE_2, Milliseconds(100), GROUP_PHASE_2, PHASE_2);
+ events.ScheduleEvent(EVENT_EJECT_2, Seconds(14), GROUP_PHASE_2, PHASE_2);
+ events.ScheduleEvent(EVENT_FEL_ACID_BREATH_2, Seconds(16), GROUP_PHASE_2, PHASE_2);
+ events.ScheduleEvent(EVENT_ARCING_SMASH_2, Seconds(8), GROUP_PHASE_2, PHASE_2);
}
+ }
- void KilledUnit(Unit* victim) override
- {
- if (victim->GetTypeId() == TYPEID_PLAYER)
- Talk(SAY_SLAY);
- }
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SLAY);
+ }
- void JustDied(Unit* /*killer*/) override
- {
- _JustDied();
- DoPlaySoundToSet(me, SOUND_ID_DEATH);
- }
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ DoPlaySoundToSet(me, SOUND_ID_DEATH);
+ }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- events.Update(diff);
+ events.Update(diff);
- while (uint32 eventId = events.ExecuteEvent())
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- switch (eventId)
- {
- case EVENT_BLOODBOIL:
- DoCast(SPELL_BLOODBOIL);
- events.Repeat(Seconds(10));
- break;
- case EVENT_ARCING_SMASH:
- DoCastVictim(SPELL_ARCING_SMASH);
- events.Repeat(Seconds(10));
- break;
- case EVENT_FEL_ACID_BREATH:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, me->GetCombatReach()))
- DoCast(target, SPELL_FEL_ACID_BREATH);
- events.Repeat(Seconds(25), Seconds(30));
- break;
- case EVENT_EJECT:
- Talk(SAY_SPECIAL);
- DoCastVictim(SPELL_EJECT);
- break;
- case EVENT_BEWILDERING_STRIKE:
- DoCastVictim(SPELL_BEWILDERING_STRIKE);
- break;
- case EVENT_CHANGE_PHASE:
- ChangePhase();
- break;
- case EVENT_START_PHASE_2:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1))
- {
- if (Unit* oldTarget = me->GetVictim())
- {
- _oldTargetGUID = oldTarget->GetGUID();
- _oldThreat = GetThreat(oldTarget);
- }
- _targetGUID = target->GetGUID();
- DoCastSelf(SPELL_FEL_RAGE_SELF, true);
- DoCast(target, SPELL_FEL_RAGE_TARGET, true);
- DoCast(target, SPELL_FEL_RAGE_2, true);
- DoCast(target, SPELL_FEL_RAGE_3, true);
- DoCast(target, SPELL_FEL_GEYSER, true);
- DoCast(target, SPELL_FEL_RAGE_TARGET_2, true);
- target->CastSpell(target, SPELL_FEL_RAGE_P, true);
- target->CastSpell(target, SPELL_TAUNT_GURTOGG, true);
- DoCastAOE(SPELL_INSIGNIFIGANCE, true);
-
- events.ScheduleEvent(EVENT_CHARGE_PLAYER, Seconds(2), GROUP_PHASE_2, PHASE_2);
-
- me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
- me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true);
- }
- else // If no other targets are found, reset phase 1
+ case EVENT_BLOODBOIL:
+ DoCast(SPELL_BLOODBOIL);
+ events.Repeat(Seconds(10));
+ break;
+ case EVENT_ARCING_SMASH:
+ DoCastVictim(SPELL_ARCING_SMASH);
+ events.Repeat(Seconds(10));
+ break;
+ case EVENT_FEL_ACID_BREATH:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, me->GetCombatReach()))
+ DoCast(target, SPELL_FEL_ACID_BREATH);
+ events.Repeat(Seconds(25), Seconds(30));
+ break;
+ case EVENT_EJECT:
+ Talk(SAY_SPECIAL);
+ DoCastVictim(SPELL_EJECT);
+ break;
+ case EVENT_BEWILDERING_STRIKE:
+ DoCastVictim(SPELL_BEWILDERING_STRIKE);
+ break;
+ case EVENT_CHANGE_PHASE:
+ ChangePhase();
+ break;
+ case EVENT_START_PHASE_2:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1))
+ {
+ if (Unit* oldTarget = me->GetVictim())
{
- events.SetPhase(PHASE_1);
- events.CancelEventGroup(GROUP_PHASE_2);
- ScheduleEvents();
- events.RescheduleEvent(EVENT_CHANGE_PHASE, Seconds(60));
+ _oldTargetGUID = oldTarget->GetGUID();
+ _oldThreat = GetThreat(oldTarget);
}
- break;
- case EVENT_CHARGE_PLAYER:
- if (Unit* target = ObjectAccessor::GetUnit(*me, _targetGUID))
- DoCast(target, SPELL_CHARGE);
- break;
- case EVENT_EJECT_2:
- DoCastVictim(SPELL_EJECT_2);
- break;
- case EVENT_FEL_ACID_BREATH_2:
- DoCastVictim(SPELL_FEL_ACID_BREATH_2);
- break;
- case EVENT_ARCING_SMASH_2:
- DoCastVictim(SPELL_ARCING_SMASH_2);
- events.Repeat(Seconds(13));
- break;
- case EVENT_BERSERK:
- DoCast(SPELL_BERSERK);
- roll_chance_i(50) ? Talk(SAY_ENRAGE) : DoPlaySoundToSet(me, SOUND_ID_ENRAGE);
- break;
- default:
- break;
- }
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- }
-
- DoMeleeAttackIfReady();
- }
-
- void ChangePhase()
- {
- if (events.IsInPhase(PHASE_1))
- {
- events.SetPhase(PHASE_2);
- events.CancelEventGroup(GROUP_PHASE_1);
- events.ScheduleEvent(EVENT_CHANGE_PHASE, Seconds(30));
- ScheduleEvents();
- }
- else if (events.IsInPhase(PHASE_2))
- {
- events.SetPhase(PHASE_1);
- events.CancelEventGroup(GROUP_PHASE_2);
- events.ScheduleEvent(EVENT_CHANGE_PHASE, Seconds(60));
- me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
- me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false);
- ScheduleEvents();
-
- // Attack the stored target
- if (Unit* oldTarget = ObjectAccessor::GetUnit(*me, _oldTargetGUID))
- if (Unit* currentTarget = ObjectAccessor::GetUnit(*me, _targetGUID))
+ _targetGUID = target->GetGUID();
+ DoCastSelf(SPELL_FEL_RAGE_SELF, true);
+ DoCast(target, SPELL_FEL_RAGE_TARGET, true);
+ DoCast(target, SPELL_FEL_RAGE_2, true);
+ DoCast(target, SPELL_FEL_RAGE_3, true);
+ DoCast(target, SPELL_FEL_GEYSER, true);
+ DoCast(target, SPELL_FEL_RAGE_TARGET_2, true);
+ target->CastSpell(target, SPELL_FEL_RAGE_P, true);
+ target->CastSpell(target, SPELL_TAUNT_GURTOGG, true);
+ DoCastAOE(SPELL_INSIGNIFIGANCE, true);
+
+ events.ScheduleEvent(EVENT_CHARGE_PLAYER, Seconds(2), GROUP_PHASE_2, PHASE_2);
+
+ me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
+ me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true);
+ }
+ else // If no other targets are found, reset phase 1
{
- ModifyThreatByPercent(currentTarget, -100);
- AttackStart(oldTarget);
- AddThreat(oldTarget, _oldThreat);
- Initialize();
+ events.SetPhase(PHASE_1);
+ events.CancelEventGroup(GROUP_PHASE_2);
+ ScheduleEvents();
+ events.RescheduleEvent(EVENT_CHANGE_PHASE, Seconds(60));
}
+ break;
+ case EVENT_CHARGE_PLAYER:
+ if (Unit* target = ObjectAccessor::GetUnit(*me, _targetGUID))
+ DoCast(target, SPELL_CHARGE);
+ break;
+ case EVENT_EJECT_2:
+ DoCastVictim(SPELL_EJECT_2);
+ break;
+ case EVENT_FEL_ACID_BREATH_2:
+ DoCastVictim(SPELL_FEL_ACID_BREATH_2);
+ break;
+ case EVENT_ARCING_SMASH_2:
+ DoCastVictim(SPELL_ARCING_SMASH_2);
+ events.Repeat(Seconds(13));
+ break;
+ case EVENT_BERSERK:
+ DoCast(SPELL_BERSERK);
+ roll_chance_i(50) ? Talk(SAY_ENRAGE) : DoPlaySoundToSet(me, SOUND_ID_ENRAGE);
+ break;
+ default:
+ break;
}
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
- private:
- ObjectGuid _targetGUID;
- ObjectGuid _oldTargetGUID;
- float _oldThreat;
- };
+ DoMeleeAttackIfReady();
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void ChangePhase()
{
- return GetBlackTempleAI<boss_gurtogg_bloodboilAI>(creature);
+ if (events.IsInPhase(PHASE_1))
+ {
+ events.SetPhase(PHASE_2);
+ events.CancelEventGroup(GROUP_PHASE_1);
+ events.ScheduleEvent(EVENT_CHANGE_PHASE, Seconds(30));
+ ScheduleEvents();
+ }
+ else if (events.IsInPhase(PHASE_2))
+ {
+ events.SetPhase(PHASE_1);
+ events.CancelEventGroup(GROUP_PHASE_2);
+ events.ScheduleEvent(EVENT_CHANGE_PHASE, Seconds(60));
+ me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
+ me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false);
+ ScheduleEvents();
+
+ // Attack the stored target
+ if (Unit* oldTarget = ObjectAccessor::GetUnit(*me, _oldTargetGUID))
+ if (Unit* currentTarget = ObjectAccessor::GetUnit(*me, _targetGUID))
+ {
+ ModifyThreatByPercent(currentTarget, -100);
+ AttackStart(oldTarget);
+ AddThreat(oldTarget, _oldThreat);
+ Initialize();
+ }
+ }
}
+
+private:
+ ObjectGuid _targetGUID;
+ ObjectGuid _oldTargetGUID;
+ float _oldThreat;
};
-class npc_fel_geyser : public CreatureScript
+struct npc_fel_geyser : public PassiveAI
{
-public:
- npc_fel_geyser() : CreatureScript("npc_fel_geyser") { }
-
- struct npc_fel_geyserAI : public PassiveAI
- {
- npc_fel_geyserAI(Creature* creature) : PassiveAI(creature) { }
-
- void Reset() override
- {
- DoCastSelf(SPELL_FEL_GEYSER_2, true);
- DoCastSelf(SPELL_BIRTH, true);
- }
- };
+ npc_fel_geyser(Creature* creature) : PassiveAI(creature) { }
- CreatureAI* GetAI(Creature* creature) const override
+ void Reset() override
{
- return GetBlackTempleAI<npc_fel_geyserAI>(creature);
+ DoCastSelf(SPELL_FEL_GEYSER_2, true);
+ DoCastSelf(SPELL_BIRTH, true);
}
};
// 42005 - Bloodboil
-class spell_gurtogg_bloodboil_bloodboil : public SpellScriptLoader
+class spell_gurtogg_bloodboil_bloodboil : public SpellScript
{
- public:
- spell_gurtogg_bloodboil_bloodboil() : SpellScriptLoader("spell_gurtogg_bloodboil_bloodboil") { }
-
- class spell_gurtogg_bloodboil_bloodboil_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gurtogg_bloodboil_bloodboil_SpellScript);
-
- void FilterTargets(std::list<WorldObject*>& targets)
- {
- if (targets.size() <= 5)
- return;
+ PrepareSpellScript(spell_gurtogg_bloodboil_bloodboil);
- // Sort the list of players
- targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster(), false));
- // Resize so we only get top 5
- targets.resize(5);
- }
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ if (targets.size() <= 5)
+ return;
- void Register() override
- {
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_gurtogg_bloodboil_bloodboil_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
- }
- };
+ // Sort the list of players
+ targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster(), false));
+ // Resize so we only get top 5
+ targets.resize(5);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gurtogg_bloodboil_bloodboil_SpellScript();
- }
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_gurtogg_bloodboil_bloodboil::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
};
// 40618 - Insignificance
-class spell_gurtogg_bloodboil_insignificance : public SpellScriptLoader
+class spell_gurtogg_bloodboil_insignificance : public SpellScript
{
-public:
- spell_gurtogg_bloodboil_insignificance() : SpellScriptLoader("spell_gurtogg_bloodboil_insignificance") { }
+ PrepareSpellScript(spell_gurtogg_bloodboil_insignificance);
- class spell_gurtogg_bloodboil_insignificance_SpellScript : public SpellScript
+ bool Validate(SpellInfo const* /*spell*/) override
{
- PrepareSpellScript(spell_gurtogg_bloodboil_insignificance_SpellScript);
-
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo({ SPELL_FEL_RAGE_TARGET });
- }
-
- void FilterTargets(std::list<WorldObject*>& targets)
- {
- targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_FEL_RAGE_TARGET));
- }
+ return ValidateSpellInfo({ SPELL_FEL_RAGE_TARGET });
+ }
- void Register() override
- {
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_gurtogg_bloodboil_insignificance_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
- }
- };
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_FEL_RAGE_TARGET));
+ }
- SpellScript* GetSpellScript() const override
+ void Register() override
{
- return new spell_gurtogg_bloodboil_insignificance_SpellScript();
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_gurtogg_bloodboil_insignificance::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
void AddSC_boss_gurtogg_bloodboil()
{
- new boss_gurtogg_bloodboil();
- new npc_fel_geyser();
- new spell_gurtogg_bloodboil_bloodboil();
- new spell_gurtogg_bloodboil_insignificance();
+ RegisterBlackTempleCreatureAI(boss_gurtogg_bloodboil);
+ RegisterBlackTempleCreatureAI(npc_fel_geyser);
+ RegisterSpellScript(spell_gurtogg_bloodboil_bloodboil);
+ RegisterSpellScript(spell_gurtogg_bloodboil_insignificance);
}
diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp
index fc6a92e203f..181a01f6745 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp
@@ -159,6 +159,8 @@ enum IllidanSpells
SPELL_DRAW_SOUL = 40904,
SPELL_DRAW_SOUL_HEAL = 40903,
SPELL_PARASITIC_SHADOWFIEND = 41917,
+ SPELL_PARASITIC_SHADOWFIEND_2 = 41914,
+ SPELL_REMOVE_PARASITIC_SHADOWFIEND = 41923,
SPELL_AGONIZING_FLAMES = 40932,
SPELL_AGONIZING_FLAMES_SELECTOR = 40834,
SPELL_FRENZY = 40683,
@@ -211,6 +213,7 @@ enum IllidanActions
ACTION_FLAME_DEAD,
ACTION_FINALIZE_AIR_PHASE,
ACTION_START_PHASE_4,
+ ACTION_RESUME_COMBAT,
ACTION_ILLIDAN_CAGED,
ACTION_START_OUTRO,
ACTION_MAIEV_DOWN_FADE
@@ -404,6 +407,12 @@ Position const IllidanDBTargetPoints[4] =
{ 660.3492f, 345.5749f, 353.2961f }
};
+Position const BladesPositions[2] =
+{
+ { 676.226013f, 325.230988f },
+ { 678.059998f, 285.220001f }
+};
+
uint32 const SummonCageTrapSpells[8] =
{
SPELL_SUMMON_CAGE_TRAP_1,
@@ -435,2118 +444,1880 @@ private:
class ChargeTargetSelector : public std::unary_function<Unit*, bool>
{
public:
- ChargeTargetSelector(Unit const* unit) : _me(unit) { }
+ ChargeTargetSelector() { }
bool operator()(Unit* unit) const
{
- return unit->GetTypeId() == TYPEID_PLAYER && _me->GetDistance2d(unit) > 25.0f;
+ return unit->GetTypeId() == TYPEID_PLAYER
+ && unit->GetDistance2d(BladesPositions[0].GetPositionX(), BladesPositions[0].GetPositionY()) > 25.0f
+ && unit->GetDistance2d(BladesPositions[1].GetPositionX(), BladesPositions[1].GetPositionY()) > 25.0f;
}
-
-private:
- Unit const* _me;
};
-class boss_illidan_stormrage : public CreatureScript
+struct boss_illidan_stormrage : public BossAI
{
-public:
- boss_illidan_stormrage() : CreatureScript("boss_illidan_stormrage") { }
+ boss_illidan_stormrage(Creature* creature) : BossAI(creature, DATA_ILLIDAN_STORMRAGE),
+ _minionsCount(0), _flameCount(0), _orientation(0.0f), _pillarIndex(0), _phase(0), _dead(false), _isDemon(false) { }
+
+ void Reset() override
+ {
+ _Reset();
+ specialEvents.Reset();
+ me->SummonCreatureGroup(SUMMON_GROUP);
+ me->LoadEquipment(1, true);
+ me->SetSheath(SHEATH_STATE_UNARMED);
+ me->SetControlled(false, UNIT_STATE_ROOT);
+ me->SetDisableGravity(false);
+ _dead = false;
+ _minionsCount = 0;
+ _flameCount = 0;
+ _phase = PHASE_1;
+ _isDemon = false;
+ if (instance->GetData(DATA_AKAMA_ILLIDAN_INTRO) && instance->GetBossState(DATA_ILLIDARI_COUNCIL) == DONE)
+ if (Creature* akama = instance->GetCreature(DATA_AKAMA))
+ akama->AI()->DoAction(ACTION_ACTIVE_AKAMA_INTRO);
+ }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _EnterCombat();
+ me->SetCanDualWield(true);
+ if (GameObject* musicController = instance->GetGameObject(DATA_ILLIDAN_MUSIC_CONTROLLER))
+ musicController->PlayDirectMusic(EVENT_BT_SUMMIT_WALK_3_SOUND_ID);
+ specialEvents.ScheduleEvent(EVENT_EVADE_CHECK, Seconds(10));
+ specialEvents.ScheduleEvent(EVENT_BERSERK, Minutes(25));
+ ScheduleEvents(GROUP_PHASE_1, GROUP_PHASE_1);
+ events.ScheduleEvent(EVENT_TAUNT, Seconds(30), Seconds(60), GROUP_PHASE_ALL);
+ }
+
+ void JustSummoned(Creature* summon) override
+ {
+ if (summon->GetEntry() == NPC_PARASITIC_SHADOWFIEND)
+ summons.Summon(summon);
+ else
+ BossAI::JustSummoned(summon);
+ }
- struct boss_illidan_stormrageAI : public BossAI
+ void ChangeOrientation(float orientation)
{
- boss_illidan_stormrageAI(Creature* creature) : BossAI(creature, DATA_ILLIDAN_STORMRAGE),
- _intro(true), _minionsCount(0), _flameCount(0), _orientation(0.0f), _pillarIndex(0), _phase(0), _dead(false), _isDemon(false) { }
+ _orientation = orientation;
+ events.ScheduleEvent(EVENT_CHANGE_ORIENTATION, Milliseconds(1), GROUP_PHASE_ALL);
+ }
+
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_ILLIDAN_KILL);
+ }
+
+ void ScheduleEvents(uint8 phase, uint8 group)
+ {
+ switch (phase)
+ {
+ case GROUP_PHASE_1:
+ events.ScheduleEvent(EVENT_FLAME_CRASH, Seconds(30), group);
+ events.ScheduleEvent(EVENT_DRAW_SOUL, Seconds(34), group);
+ events.ScheduleEvent(EVENT_SHEAR, Seconds(10), group);
+ events.ScheduleEvent(EVENT_PARASITIC_SHADOWFIEND, Seconds(26), group);
+ break;
+ case GROUP_PHASE_2:
+ events.ScheduleEvent(EVENT_FIREBALL, Seconds(1), Seconds(8), group);
+ events.ScheduleEvent(EVENT_EYE_BLAST, Seconds(1), Seconds(30), group);
+ if (roll_chance_i(50))
+ events.ScheduleEvent(EVENT_DARK_BARRAGE, Seconds(1), Seconds(20), group);
+ break;
+ case GROUP_PHASE_3:
+ ScheduleEvents(GROUP_PHASE_1, group);
+ events.ScheduleEvent(EVENT_AGONIZING_FLAMES, Seconds(21), group);
+ events.ScheduleEvent(EVENT_DEMON, Seconds(60), group);
+ break;
+ case GROUP_PHASE_DEMON:
+ events.ScheduleEvent(EVENT_SHADOW_BLAST, Seconds(1), group);
+ events.ScheduleEvent(EVENT_FLAME_BURST, Seconds(6), group);
+ events.ScheduleEvent(EVENT_SHADOW_DEMON, Seconds(18), Seconds(30), group);
+ break;
+ case GROUP_PHASE_4:
+ ScheduleEvents(GROUP_PHASE_3, group);
+ events.ScheduleEvent(EVENT_FRENZY, Seconds(40), group);
+ break;
+ default:
+ break;
+ }
+ }
- void Reset() override
+ void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
+ {
+ if (summon->GetEntry() == NPC_ILLIDARI_ELITE)
+ _minionsCount--;
+ }
+
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ summons.DespawnAll();
+ specialEvents.Reset();
+ _DespawnAtEvade();
+ }
+
+ void DoAction(int32 actionId) override
+ {
+ switch (actionId)
{
- _Reset();
- specialEvents.Reset();
- me->SummonCreatureGroup(SUMMON_GROUP);
- me->LoadEquipment(1, true);
- me->SetSheath(SHEATH_STATE_UNARMED);
- me->SetControlled(false, UNIT_STATE_ROOT);
- me->SetDisableGravity(false);
- _dead = false;
- _minionsCount = 0;
- _flameCount = 0;
- _phase = PHASE_1;
- _isDemon = false;
- if (_intro && instance->GetBossState(DATA_ILLIDARI_COUNCIL) == DONE)
+ case ACTION_START_ENCOUNTER:
+ events.SetPhase(PHASE_INTRO);
+ me->RemoveAurasDueToSpell(SPELL_KNEEL);
+ events.ScheduleEvent(EVENT_START_INTRO, Seconds(2), GROUP_PHASE_ALL);
+ events.ScheduleEvent(EVENT_UNCONVINCED, Seconds(24), GROUP_PHASE_ALL);
+ if (Creature* akama = instance->GetCreature(DATA_AKAMA))
+ akama->AI()->DoAction(ACTION_FREE);
+ break;
+ case ACTION_INTRO_DONE:
+ instance->SetData(DATA_AKAMA_ILLIDAN_INTRO, 0);
+ break;
+ case ACTION_START_MINIONS:
+ Talk(SAY_ILLIDAN_MINION);
if (Creature* akama = instance->GetCreature(DATA_AKAMA))
- akama->AI()->DoAction(ACTION_ACTIVE_AKAMA_INTRO);
+ akama->AI()->DoAction(ACTION_START_MINIONS);
+ break;
+ case ACTION_START_MINIONS_WEAVE:
+ events.ScheduleEvent(EVENT_MINIONS_WEAVE, Milliseconds(1), GROUP_PHASE_ALL);
+ break;
+ case ACTION_START_PHASE_2:
+ {
+ me->SetReactState(REACT_PASSIVE);
+ me->AttackStop();
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
+ me->SetDisableGravity(true);
+ DoPlaySoundToSet(me, ILLIDAN_TAKEOFF_SOUND_ID);
+ events.ScheduleEvent(EVENT_FLY, Seconds(1), GROUP_PHASE_ALL);
+ events.CancelEventGroup(GROUP_PHASE_1);
+ break;
+ }
+ case ACTION_FLAME_DEAD:
+ _flameCount++;
+ if (_flameCount == 2)
+ {
+ _flameCount = 0;
+ DoAction(ACTION_FINALIZE_AIR_PHASE);
+ }
+ break;
+ case ACTION_FINALIZE_AIR_PHASE:
+ me->InterruptNonMeleeSpells(false);
+ me->GetMotionMaster()->Clear();
+ events.CancelEventGroup(GROUP_PHASE_2);
+ _phase = PHASE_3;
+ events.CancelEvent(EVENT_FLY_TO_RANDOM_PILLAR);
+ me->GetMotionMaster()->MovePoint(POINT_ILLIDAN_MIDDLE, IllidanMiddlePoint);
+ break;
+ case ACTION_START_PHASE_4:
+ events.CancelEventGroup(GROUP_PHASE_3);
+ DoCastSelf(SPELL_SHADOW_PRISON, true);
+ summons.DoAction(ACTION_START_PHASE_4, EntryCheckPredicate(NPC_PARASITIC_SHADOWFIEND));
+ me->SetReactState(REACT_PASSIVE);
+ me->AttackStop();
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ events.ScheduleEvent(EVENT_SHADOW_PRISON_TEXT, Milliseconds(500), GROUP_PHASE_ALL);
+ break;
+ case ACTION_ILLIDAN_CAGED:
+ for (uint32 summonSpell : SummonCageTrapSpells)
+ DoCastSelf(summonSpell, true);
+ DoCastSelf(SPELL_CAGE_TRAP, true);
+ break;
+ case ACTION_START_OUTRO:
+ me->AttackStop();
+ events.Reset();
+ specialEvents.Reset();
+ DoCastSelf(SPELL_DEATH, true);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ events.ScheduleEvent(EVENT_DEFEATED_TEXT, Seconds(4));
+ break;
+ default:
+ break;
}
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ instance->SetBossState(DATA_ILLIDAN_STORMRAGE, DONE);
+ events.Reset();
+ }
- void EnterCombat(Unit* /*who*/) override
+ void MovementInform(uint32 type, uint32 pointId) override
+ {
+ if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE)
+ return;
+
+ switch (pointId)
{
- _EnterCombat();
- me->SetCanDualWield(true);
- if (GameObject* musicController = instance->GetGameObject(DATA_ILLIDAN_MUSIC_CONTROLLER))
- musicController->PlayDirectMusic(EVENT_BT_SUMMIT_WALK_3_SOUND_ID);
- specialEvents.ScheduleEvent(EVENT_EVADE_CHECK, Seconds(10));
- specialEvents.ScheduleEvent(EVENT_BERSERK, Minutes(25));
- ScheduleEvents(GROUP_PHASE_1, GROUP_PHASE_1);
- events.ScheduleEvent(EVENT_TAUNT, Seconds(30), Seconds(60), GROUP_PHASE_ALL);
+ case POINT_THROW_GLAIVE:
+ DoPlaySoundToSet(me, ILLIDAN_WARGLAIVE_SOUND_ID);
+ events.ScheduleEvent(EVENT_THROW_WARGLAIVE, Seconds(2), GROUP_PHASE_ALL);
+ events.ScheduleEvent(EVENT_FACE_MIDDLE, Milliseconds(1), GROUP_PHASE_ALL);
+ break;
+ case POINT_RANDOM_PILLAR:
+ {
+ float orientation = IllidanPhase2Positions[_pillarIndex].GetOrientation();
+ ChangeOrientation(orientation);
+ ScheduleEvents(GROUP_PHASE_2, GROUP_PHASE_2);
+ break;
+ }
+ case POINT_ILLIDAN_MIDDLE:
+ {
+ float orientation = IllidanMiddlePoint.GetOrientation();
+ ChangeOrientation(orientation);
+
+ std::list<Creature*> triggers;
+ GetCreatureListWithEntryInGrid(triggers, me, NPC_BLADE_OF_AZZINOTH, 150.0f);
+ for (Creature* trigger : triggers)
+ trigger->CastSpell(trigger, SPELL_GLAIVE_RETURNS, true);
+
+ events.ScheduleEvent(EVENT_GLAIVE_EMOTE, Seconds(3), GROUP_PHASE_ALL);
+ break;
+ }
+ default:
+ break;
}
+ }
+
+ void EnterEvadeModeIfNeeded()
+ {
+ Map::PlayerList const& players = me->GetMap()->GetPlayers();
+ for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i)
+ if (Player* player = i->GetSource())
+ if (player->IsAlive() && !player->IsGameMaster() && CheckBoundary(player))
+ return;
- void ChangeOrientation(float orientation)
+ EnterEvadeMode(EVADE_REASON_NO_HOSTILES);
+ }
+
+ void SummonMinions()
+ {
+ uint8 needSummon = MAX_MINIONS_NUMBER - _minionsCount;
+ for (uint8 i = 0; i < needSummon; ++i)
{
- _orientation = orientation;
- events.ScheduleEvent(EVENT_CHANGE_ORIENTATION, Milliseconds(1), GROUP_PHASE_ALL);
+ _minionsCount++;
+ me->SummonCreature(NPC_ILLIDARI_ELITE, MinionsSpawnPositions[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 6000);
}
+ }
- void KilledUnit(Unit* victim) override
+ void DamageTaken(Unit* who, uint32 &damage) override
+ {
+
+ if (damage >= me->GetHealth() && who->GetGUID() != me->GetGUID())
{
- if (victim->GetTypeId() == TYPEID_PLAYER)
- Talk(SAY_ILLIDAN_KILL);
+ damage = me->GetHealth() - 1;
+ if (!_dead)
+ {
+ if (_isDemon)
+ {
+ events.Reset();
+ specialEvents.Reset();
+ DoCastSelf(SPELL_DEMON_TRANSFORM_1);
+ return;
+ }
+ _dead = true;
+ summons.DespawnEntry(NPC_PARASITIC_SHADOWFIEND);
+ DoCastSelf(SPELL_REMOVE_PARASITIC_SHADOWFIEND, true);
+ DoAction(ACTION_START_OUTRO);
+ if (Creature* maiev = instance->GetCreature(DATA_MAIEV))
+ maiev->AI()->DoAction(ACTION_START_OUTRO);
+ }
+ }
+ else if (me->HealthBelowPct(90) && _phase < PHASE_MINIONS)
+ {
+ _phase = PHASE_MINIONS;
+ DoAction(ACTION_START_MINIONS);
+ }
+ else if (me->HealthBelowPct(65) && _phase < PHASE_2)
+ {
+ _phase = PHASE_2;
+ DoAction(ACTION_START_PHASE_2);
}
+ else if (me->HealthBelowPct(30) && _phase < PHASE_4)
+ {
+ _phase = PHASE_4;
- void ScheduleEvents(uint8 phase, uint8 group)
+ if (_isDemon)
+ {
+ _isDemon = false;
+ me->SetControlled(false, UNIT_STATE_ROOT);
+ events.CancelEventGroup(GROUP_PHASE_DEMON);
+ me->InterruptNonMeleeSpells(false);
+ DoCastSelf(SPELL_DEMON_TRANSFORM_1, true);
+ events.ScheduleEvent(EVENT_PHASE_4_DELAYED, Seconds(12), GROUP_PHASE_ALL);
+ }
+ else
+ DoAction(ACTION_START_PHASE_4);
+ }
+ }
+
+ void ExecuteSpecialEvents()
+ {
+ while (uint32 eventId = specialEvents.ExecuteEvent())
{
- switch (phase)
+ switch (eventId)
{
- case GROUP_PHASE_1:
- events.ScheduleEvent(EVENT_FLAME_CRASH, Seconds(30), group);
- events.ScheduleEvent(EVENT_DRAW_SOUL, Seconds(34), group);
- events.ScheduleEvent(EVENT_SHEAR, Seconds(10), group);
- events.ScheduleEvent(EVENT_PARASITIC_SHADOWFIEND, Seconds(26), group);
- break;
- case GROUP_PHASE_2:
- events.ScheduleEvent(EVENT_FIREBALL, Seconds(1), Seconds(8), group);
- events.ScheduleEvent(EVENT_EYE_BLAST, Seconds(1), Seconds(30), group);
- if (roll_chance_i(50))
- events.ScheduleEvent(EVENT_DARK_BARRAGE, Seconds(1), Seconds(20), group);
- break;
- case GROUP_PHASE_3:
- ScheduleEvents(GROUP_PHASE_1, group);
- events.ScheduleEvent(EVENT_AGONIZING_FLAMES, Seconds(21), group);
- events.ScheduleEvent(EVENT_DEMON, Seconds(60), group);
- break;
- case GROUP_PHASE_DEMON:
- events.ScheduleEvent(EVENT_SHADOW_BLAST, Seconds(1), group);
- events.ScheduleEvent(EVENT_FLAME_BURST, Seconds(6), group);
- events.ScheduleEvent(EVENT_SHADOW_DEMON, Seconds(18), Seconds(30), group);
- break;
- case GROUP_PHASE_4:
- ScheduleEvents(GROUP_PHASE_3, group);
- events.ScheduleEvent(EVENT_FRENZY, Seconds(40), group);
+ case EVENT_BERSERK:
+ Talk(SAY_ILLIDAN_ENRAGE);
+ DoCastSelf(SPELL_BERSERK, true);
+ break;
+ case EVENT_CANCEL_DEMON_FORM:
+ me->InterruptNonMeleeSpells(false);
+ me->SetControlled(false, UNIT_STATE_ROOT);
+ events.CancelEventGroup(GROUP_PHASE_DEMON);
+ DoCastSelf(SPELL_DEMON_TRANSFORM_1, true);
+ events.ScheduleEvent(EVENT_RESUME_COMBAT_DEMON, Seconds(12), GROUP_PHASE_ALL);
+ _isDemon = false;
+ break;
+ case EVENT_EVADE_CHECK:
+ EnterEvadeModeIfNeeded();
+ specialEvents.Repeat(Seconds(10));
break;
default:
break;
}
}
+ }
- void JustSummoned(Creature* summon) override
- {
- BossAI::JustSummoned(summon);
- if (summon->GetEntry() == NPC_ILLIDARI_ELITE)
- if (Creature* akama = instance->GetCreature(DATA_AKAMA))
- AddThreat(akama, 1000.0f, summon);
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO))
+ return;
- void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
- {
- if (summon->GetEntry() == NPC_ILLIDARI_ELITE)
- _minionsCount--;
- }
+ specialEvents.Update(diff);
- void EnterEvadeMode(EvadeReason /*why*/) override
- {
- summons.DespawnAll();
- specialEvents.Reset();
- _DespawnAtEvade();
- }
+ ExecuteSpecialEvents();
- void DoAction(int32 actionId) override
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
{
- switch (actionId)
+ switch (eventId)
{
- case ACTION_START_ENCOUNTER:
- events.SetPhase(PHASE_INTRO);
- me->RemoveAurasDueToSpell(SPELL_KNEEL);
- events.ScheduleEvent(EVENT_START_INTRO, Seconds(2), GROUP_PHASE_ALL);
- events.ScheduleEvent(EVENT_UNCONVINCED, Seconds(24), GROUP_PHASE_ALL);
- if (Creature* akama = instance->GetCreature(DATA_AKAMA))
- akama->AI()->DoAction(ACTION_FREE);
+ case EVENT_START_INTRO:
+ Talk(SAY_ILLIDAN_DUPLICITY);
+ break;
+ case EVENT_UNCONVINCED:
+ Talk(SAY_ILLIDAN_UNCONVINCED);
+ events.ScheduleEvent(EVENT_PREPARED, Seconds(14), GROUP_PHASE_ALL);
break;
- case ACTION_INTRO_DONE:
- _intro = false;
+ case EVENT_PREPARED:
+ Talk(SAY_ILLIDAN_PREPARED);
+ me->SetSheath(SHEATH_STATE_MELEE);
+ events.ScheduleEvent(EVENT_ENCOUNTER_START, Seconds(3), GROUP_PHASE_ALL);
break;
- case ACTION_START_MINIONS:
- Talk(SAY_ILLIDAN_MINION);
+ case EVENT_ENCOUNTER_START:
+ me->SetImmuneToAll(false);
+ DoZoneInCombat();
if (Creature* akama = instance->GetCreature(DATA_AKAMA))
- akama->AI()->DoAction(ACTION_START_MINIONS);
+ akama->AI()->DoAction(ACTION_START_ENCOUNTER);
break;
- case ACTION_START_MINIONS_WEAVE:
- events.ScheduleEvent(EVENT_MINIONS_WEAVE, Milliseconds(1), GROUP_PHASE_ALL);
+ case EVENT_FLAME_CRASH:
+ DoCastVictim(SPELL_FLAME_CRASH);
+ events.Repeat(Seconds(30));
break;
- case ACTION_START_PHASE_2:
- {
- me->SetReactState(REACT_PASSIVE);
- me->AttackStop();
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
- me->SetDisableGravity(true);
- DoPlaySoundToSet(me, ILLIDAN_TAKEOFF_SOUND_ID);
- events.ScheduleEvent(EVENT_FLY, Seconds(1), GROUP_PHASE_ALL);
- events.CancelEventGroup(GROUP_PHASE_1);
+ case EVENT_DRAW_SOUL:
+ DoCastAOE(SPELL_DRAW_SOUL);
+ events.Repeat(Seconds(34));
break;
- }
- case ACTION_FLAME_DEAD:
- _flameCount++;
- if (_flameCount == 2)
- {
- _flameCount = 0;
- DoAction(ACTION_FINALIZE_AIR_PHASE);
- }
+ case EVENT_SHEAR:
+ DoCastVictim(SPELL_SHEAR);
+ events.Repeat(Seconds(12));
break;
- case ACTION_FINALIZE_AIR_PHASE:
- me->InterruptNonMeleeSpells(false);
- me->GetMotionMaster()->Clear();
- events.CancelEventGroup(GROUP_PHASE_2);
- _phase = PHASE_3;
- events.CancelEvent(EVENT_FLY_TO_RANDOM_PILLAR);
- me->GetMotionMaster()->MovePoint(POINT_ILLIDAN_MIDDLE, IllidanMiddlePoint);
+ case EVENT_PARASITIC_SHADOWFIEND:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ DoCast(target, SPELL_PARASITIC_SHADOWFIEND);
+ events.Repeat(Seconds(30));
break;
- case ACTION_START_PHASE_4:
- events.CancelEventGroup(GROUP_PHASE_3);
- DoCastSelf(SPELL_SHADOW_PRISON, true);
- me->SetReactState(REACT_PASSIVE);
- me->AttackStop();
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- events.ScheduleEvent(EVENT_SHADOW_PRISON_TEXT, Milliseconds(500), GROUP_PHASE_ALL);
+ case EVENT_MINIONS_WEAVE:
+ if (_dead)
+ return;
+ SummonMinions();
+ events.Repeat(Seconds(30));
break;
- case ACTION_ILLIDAN_CAGED:
- for (uint32 summonSpell : SummonCageTrapSpells)
- DoCastSelf(summonSpell, true);
- DoCastSelf(SPELL_CAGE_TRAP, true);
+ case EVENT_MOVE_TO_WARGLAIVE_POINT:
+ {
+ Position pos;
+ std::list<Creature*> triggers;
+ GetCreatureListWithEntryInGrid(triggers, me, NPC_GLAIVE_WORLD_TRIGGER, 150.0f);
+ triggers.remove_if([](WorldObject* unit)
+ {
+ return unit->GetPositionZ() < 355.0f || unit->GetPositionZ() > 365.0f;
+ });
+
+ if (triggers.empty())
+ break;
+
+ triggers.sort(Trinity::ObjectDistanceOrderPred(me));
+ pos.Relocate(triggers.front());
+ pos.SetOrientation(0.0f);
+ me->GetMotionMaster()->MovePoint(POINT_THROW_GLAIVE, pos);
+ if (GameObject* musicController = instance->GetGameObject(DATA_ILLIDAN_MUSIC_CONTROLLER))
+ musicController->PlayDirectMusic(EVENT_BT_STORM_WALK_HERO_2_SOUND_ID);
break;
- case ACTION_START_OUTRO:
- me->AttackStop();
- events.Reset();
- specialEvents.Reset();
- DoCastSelf(SPELL_DEATH, true);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- events.ScheduleEvent(EVENT_DEFEATED_TEXT, Seconds(4));
+ }
+ case EVENT_THROW_WARGLAIVE:
+ DoCastAOE(SPELL_THROW_GLAIVE);
+ events.ScheduleEvent(EVENT_THROW_WARGLAIVE_2, Seconds(1), GROUP_PHASE_ALL);
break;
- default:
+ case EVENT_THROW_WARGLAIVE_2:
+ DoCastAOE(SPELL_THROW_GLAIVE2);
+ me->SetSheath(SHEATH_STATE_UNARMED);
+ events.ScheduleEvent(EVENT_FLY_TO_RANDOM_PILLAR, Seconds(2), GROUP_PHASE_ALL);
break;
- }
- }
-
- void JustDied(Unit* /*killer*/) override
- {
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- instance->SetBossState(DATA_ILLIDAN_STORMRAGE, DONE);
- events.Reset();
- }
-
- void MovementInform(uint32 type, uint32 pointId) override
- {
- if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE)
- return;
-
- switch (pointId)
- {
- case POINT_THROW_GLAIVE:
- DoPlaySoundToSet(me, ILLIDAN_WARGLAIVE_SOUND_ID);
- events.ScheduleEvent(EVENT_THROW_WARGLAIVE, Seconds(2), GROUP_PHASE_ALL);
- events.ScheduleEvent(EVENT_FACE_MIDDLE, Milliseconds(1), GROUP_PHASE_ALL);
+ case EVENT_CHANGE_ORIENTATION:
+ me->SetFacingTo(_orientation);
break;
- case POINT_RANDOM_PILLAR:
+ case EVENT_FLY:
+ ChangeOrientation(3.137039f);
+ events.ScheduleEvent(EVENT_MOVE_TO_WARGLAIVE_POINT, Seconds(6), GROUP_PHASE_ALL);
+ break;
+ case EVENT_FLY_TO_RANDOM_PILLAR:
{
- float orientation = IllidanPhase2Positions[_pillarIndex].GetOrientation();
- ChangeOrientation(orientation);
- ScheduleEvents(GROUP_PHASE_2, GROUP_PHASE_2);
+ events.CancelEventGroup(GROUP_PHASE_2);
+ _pillarIndex = urand(0, 3);
+ me->GetMotionMaster()->MovePoint(POINT_RANDOM_PILLAR, IllidanPhase2Positions[_pillarIndex]);
+ events.Repeat(Seconds(30));
break;
}
- case POINT_ILLIDAN_MIDDLE:
+ case EVENT_FACE_MIDDLE:
{
- float orientation = IllidanMiddlePoint.GetOrientation();
- ChangeOrientation(orientation);
-
- std::list<Creature*> triggers;
- GetCreatureListWithEntryInGrid(triggers, me, NPC_BLADE_OF_AZZINOTH, 150.0f);
- for (Creature* trigger : triggers)
- trigger->CastSpell(trigger, SPELL_GLAIVE_RETURNS, true);
-
- events.ScheduleEvent(EVENT_GLAIVE_EMOTE, Seconds(3), GROUP_PHASE_ALL);
+ float angle = me->GetAngle(IllidanMiddlePoint);
+ me->SetFacingTo(angle);
break;
}
- default:
- break;
- }
- }
-
- void EnterEvadeModeIfNeeded()
- {
- Map::PlayerList const& players = me->GetMap()->GetPlayers();
- for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i)
- if (Player* player = i->GetSource())
- if (player->IsAlive() && !player->IsGameMaster() && CheckBoundary(player))
- return;
-
- EnterEvadeMode(EVADE_REASON_NO_HOSTILES);
- }
-
- void SummonMinions()
- {
- uint8 needSummon = MAX_MINIONS_NUMBER - _minionsCount;
- for (uint8 i = 0; i < needSummon; ++i)
- {
- _minionsCount++;
- me->SummonCreature(NPC_ILLIDARI_ELITE, MinionsSpawnPositions[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 6000);
- }
- }
-
- void DamageTaken(Unit* who, uint32 &damage) override
- {
-
- if (damage >= me->GetHealth() && who->GetGUID() != me->GetGUID())
- {
- damage = me->GetHealth() - 1;
- if (!_dead)
+ case EVENT_EYE_BLAST:
{
- if (_isDemon)
+ events.CancelEvent(EVENT_DARK_BARRAGE);
+ Position pos = IllidanDBTargetSpawnPositions[_pillarIndex];
+ if (TempSummon* dbTarget = me->SummonCreature(NPC_ILLIDAN_DB_TARGET, pos, TEMPSUMMON_MANUAL_DESPAWN))
{
- events.Reset();
- specialEvents.Reset();
- DoCastSelf(SPELL_DEMON_TRANSFORM_1);
- return;
+ Talk(SAY_ILLIDAN_EYE_BLAST);
+ DoCast(dbTarget, SPELL_EYE_BLAST);
+ dbTarget->GetMotionMaster()->MovePoint(POINT_DB_TARGET, IllidanDBTargetPoints[_pillarIndex]);
}
- _dead = true;
- DoAction(ACTION_START_OUTRO);
- if (Creature* maiev = instance->GetCreature(DATA_MAIEV))
- maiev->AI()->DoAction(ACTION_START_OUTRO);
+ break;
}
- }
- else if (me->HealthBelowPct(90) && _phase < PHASE_MINIONS)
- {
- _phase = PHASE_MINIONS;
- DoAction(ACTION_START_MINIONS);
- }
- else if (me->HealthBelowPct(65) && _phase < PHASE_2)
- {
- _phase = PHASE_2;
- DoAction(ACTION_START_PHASE_2);
- }
- else if (me->HealthBelowPct(30) && _phase < PHASE_4)
- {
- _phase = PHASE_4;
-
- if (_isDemon)
+ case EVENT_DARK_BARRAGE:
{
- _isDemon = false;
- me->SetControlled(false, UNIT_STATE_ROOT);
- events.CancelEventGroup(GROUP_PHASE_DEMON);
- me->InterruptNonMeleeSpells(false);
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150.0f, true))
+ DoCast(target, SPELL_DARK_BARRAGE);
+ events.RescheduleEvent(EVENT_EYE_BLAST, Seconds(5), GROUP_PHASE_2);
+ uint32 currentTime = events.GetNextEventTime(EVENT_FLY_TO_RANDOM_PILLAR);
+ events.RescheduleEvent(EVENT_FLY_TO_RANDOM_PILLAR, Seconds(currentTime) + Seconds(30), GROUP_PHASE_2);
+ break;
+ }
+ case EVENT_FIREBALL:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150.0f, true))
+ DoCast(target, SPELL_FIREBALL);
+ events.Repeat(Seconds(2), Seconds(4));
+ break;
+ case EVENT_GLAIVE_EMOTE:
+ me->SetDisableGravity(false);
+ me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
+ me->SetSheath(SHEATH_STATE_MELEE);
+ events.ScheduleEvent(EVENT_RESUME_COMBAT, Seconds(3), GROUP_PHASE_ALL);
+ break;
+ case EVENT_RESUME_COMBAT:
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->SetReactState(REACT_AGGRESSIVE);
+ ScheduleEvents(GROUP_PHASE_3, GROUP_PHASE_3);
+ if (GameObject* musicController = instance->GetGameObject(DATA_ILLIDAN_MUSIC_CONTROLLER))
+ musicController->PlayDirectMusic(EVENT_BT_STORM_WALK_UNI_3_SOUND_ID);
+ break;
+ case EVENT_AGONIZING_FLAMES:
+ DoCastSelf(SPELL_AGONIZING_FLAMES_SELECTOR);
+ events.Repeat(Seconds(53));
+ break;
+ case EVENT_DEMON:
+ me->SetControlled(true, UNIT_STATE_ROOT);
+ _isDemon = true;
+ events.CancelEventGroup(_phase == PHASE_3 ? GROUP_PHASE_3 : GROUP_PHASE_4);
+ me->LoadEquipment(0, true);
DoCastSelf(SPELL_DEMON_TRANSFORM_1, true);
- events.ScheduleEvent(EVENT_PHASE_4_DELAYED, Seconds(12), GROUP_PHASE_ALL);
+ events.ScheduleEvent(EVENT_DEMON_TEXT, Seconds(2), GROUP_PHASE_ALL);
+ specialEvents.ScheduleEvent(EVENT_CANCEL_DEMON_FORM, Minutes(1) + Seconds(12));
+ events.ScheduleEvent(EVENT_SCHEDULE_DEMON_SPELLS, Seconds(15));
+ break;
+ case EVENT_SCHEDULE_DEMON_SPELLS:
+ ResetThreatList();
+ ScheduleEvents(GROUP_PHASE_DEMON, GROUP_PHASE_DEMON);
+ break;
+ case EVENT_DEMON_TEXT:
+ Talk(SAY_ILLIDAN_MORPH);
+ break;
+ case EVENT_RESUME_COMBAT_DEMON:
+ {
+ uint8 group = _phase == PHASE_3 ? GROUP_PHASE_3 : GROUP_PHASE_4;
+ ResetThreatList();
+ ScheduleEvents(group, group);
+ me->LoadEquipment(1, true);
+ break;
}
- else
+ case EVENT_FLAME_BURST:
+ DoCastSelf(SPELL_FLAME_BURST);
+ events.Repeat(Seconds(22));
+ break;
+ case EVENT_SHADOW_DEMON:
+ DoCastSelf(SPELL_SUMMON_SHADOWDEMON);
+ break;
+ case EVENT_SHADOW_BLAST:
+ DoCastVictim(SPELL_SHADOW_BLAST);
+ events.Repeat(Seconds(2));
+ break;
+ case EVENT_PHASE_4_DELAYED:
DoAction(ACTION_START_PHASE_4);
- }
- }
-
- void ExecuteSpecialEvents()
- {
- while (uint32 eventId = specialEvents.ExecuteEvent())
- {
- switch (eventId)
+ break;
+ case EVENT_SHADOW_PRISON_TEXT:
+ Talk(SAY_ILLIDAN_SHADOW_PRISON);
+ events.ScheduleEvent(EVENT_SUMMON_MAIEV, Seconds(9), GROUP_PHASE_ALL);
+ break;
+ case EVENT_SUMMON_MAIEV:
+ DoCastSelf(SPELL_SUMMON_MAIEV);
+ if (Creature* maiev = instance->GetCreature(DATA_MAIEV))
+ me->SetFacingToObject(maiev);
+ events.ScheduleEvent(EVENT_CONFRONT_MAIEV_TEXT, Seconds(9), GROUP_PHASE_ALL);
+ break;
+ case EVENT_CONFRONT_MAIEV_TEXT:
+ Talk(SAY_ILLIDAN_CONFRONT_MAIEV);
+ events.ScheduleEvent(EVENT_RESUME_COMBAT_PHASE_4, Seconds(13), GROUP_PHASE_ALL);
+ break;
+ case EVENT_RESUME_COMBAT_PHASE_4:
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->SetReactState(REACT_AGGRESSIVE);
+ ScheduleEvents(GROUP_PHASE_4, GROUP_PHASE_4);
+ summons.DoAction(ACTION_RESUME_COMBAT, EntryCheckPredicate(NPC_PARASITIC_SHADOWFIEND));
+ break;
+ case EVENT_FRENZY:
+ DoCastSelf(SPELL_FRENZY);
+ Talk(SAY_ILLIDAN_FRENZY);
+ events.Repeat(Seconds(40));
+ break;
+ case EVENT_TAUNT:
+ Talk(SAY_ILLIDAN_TAUNT);
+ events.Repeat(Seconds(30), Seconds(60));
+ break;
+ case EVENT_DEFEATED_TEXT:
+ Talk(SAY_ILLIDAN_DEFEATED);
+ if (GameObject* musicController = instance->GetGameObject(DATA_ILLIDAN_MUSIC_CONTROLLER))
+ musicController->PlayDirectMusic(EVENT_BT_ARRIVAL_WALK_HERO_1_SOUND_ID);
+ events.ScheduleEvent(EVENT_QUIET_SUICIDE, Seconds(18));
+ break;
+ case EVENT_QUIET_SUICIDE:
{
- case EVENT_BERSERK:
- Talk(SAY_ILLIDAN_ENRAGE);
- DoCastSelf(SPELL_BERSERK, true);
- break;
- case EVENT_CANCEL_DEMON_FORM:
- me->InterruptNonMeleeSpells(false);
- me->SetControlled(false, UNIT_STATE_ROOT);
- events.CancelEventGroup(GROUP_PHASE_DEMON);
- DoCastSelf(SPELL_DEMON_TRANSFORM_1, true);
- events.ScheduleEvent(EVENT_RESUME_COMBAT_DEMON, Seconds(12), GROUP_PHASE_ALL);
- _isDemon = false;
- break;
- case EVENT_EVADE_CHECK:
- EnterEvadeModeIfNeeded();
- specialEvents.Repeat(Seconds(10));
- break;
- default:
- break;
+ DoCastSelf(SPELL_QUIET_SUICIDE, true);
+ if (Creature* akama = instance->GetCreature(DATA_AKAMA))
+ akama->AI()->DoAction(ACTION_START_OUTRO);
+ ObjectGuid _akamaGUID = instance->GetGuidData(DATA_AKAMA);
+ ObjectGuid _maievGUID = instance->GetGuidData(DATA_MAIEV);
+ summons.DespawnIf([_akamaGUID, _maievGUID](ObjectGuid unitGuid)
+ {
+ return unitGuid != _akamaGUID && unitGuid != _maievGUID;
+ });
+ break;
}
+ default:
+ break;
}
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO))
- return;
-
- specialEvents.Update(diff);
-
- ExecuteSpecialEvents();
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
+ }
- events.Update(diff);
+ DoMeleeAttackIfReady();
+ }
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_START_INTRO:
- Talk(SAY_ILLIDAN_DUPLICITY);
- break;
- case EVENT_UNCONVINCED:
- Talk(SAY_ILLIDAN_UNCONVINCED);
- events.ScheduleEvent(EVENT_PREPARED, Seconds(14), GROUP_PHASE_ALL);
- break;
- case EVENT_PREPARED:
- Talk(SAY_ILLIDAN_PREPARED);
- me->SetSheath(SHEATH_STATE_MELEE);
- events.ScheduleEvent(EVENT_ENCOUNTER_START, Seconds(3), GROUP_PHASE_ALL);
- break;
- case EVENT_ENCOUNTER_START:
- me->SetImmuneToAll(false);
- DoZoneInCombat();
- if (Creature* akama = instance->GetCreature(DATA_AKAMA))
- akama->AI()->DoAction(ACTION_START_ENCOUNTER);
- break;
- case EVENT_FLAME_CRASH:
- DoCastVictim(SPELL_FLAME_CRASH);
- events.Repeat(Seconds(30));
- break;
- case EVENT_DRAW_SOUL:
- DoCastAOE(SPELL_DRAW_SOUL);
- events.Repeat(Seconds(34));
- break;
- case EVENT_SHEAR:
- DoCastVictim(SPELL_SHEAR);
- events.Repeat(Seconds(12));
- break;
- case EVENT_PARASITIC_SHADOWFIEND:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1))
- DoCast(target, SPELL_PARASITIC_SHADOWFIEND);
- events.Repeat(Seconds(30));
- break;
- case EVENT_MINIONS_WEAVE:
- SummonMinions();
- events.Repeat(Seconds(30));
- break;
- case EVENT_MOVE_TO_WARGLAIVE_POINT:
- {
- Position pos;
- std::list<Creature*> triggers;
- GetCreatureListWithEntryInGrid(triggers, me, NPC_GLAIVE_WORLD_TRIGGER, 150.0f);
- triggers.remove_if([](WorldObject* unit)
- {
- return unit->GetPositionZ() < 355.0f || unit->GetPositionZ() > 365.0f;
- });
+private:
+ uint8 _minionsCount;
+ uint8 _flameCount;
+ float _orientation;
+ uint8 _pillarIndex;
+ uint8 _phase;
+ bool _dead;
+ bool _isDemon;
+ EventMap specialEvents;
+};
- if (triggers.empty())
- break;
+struct npc_akama_illidan : public ScriptedAI
+{
+ npc_akama_illidan(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()),
+ _orientation(0.0f), _isTeleportToMinions(false) { }
- triggers.sort(Trinity::ObjectDistanceOrderPred(me));
- pos.Relocate(triggers.front());
- pos.SetOrientation(0.0f);
- me->GetMotionMaster()->MovePoint(POINT_THROW_GLAIVE, pos);
- if (GameObject* musicController = instance->GetGameObject(DATA_ILLIDAN_MUSIC_CONTROLLER))
- musicController->PlayDirectMusic(EVENT_BT_STORM_WALK_HERO_2_SOUND_ID);
- break;
- }
- case EVENT_THROW_WARGLAIVE:
- DoCastAOE(SPELL_THROW_GLAIVE);
- events.ScheduleEvent(EVENT_THROW_WARGLAIVE_2, Seconds(1), GROUP_PHASE_ALL);
- break;
- case EVENT_THROW_WARGLAIVE_2:
- DoCastAOE(SPELL_THROW_GLAIVE2);
- me->SetSheath(SHEATH_STATE_UNARMED);
- events.ScheduleEvent(EVENT_FLY_TO_RANDOM_PILLAR, Seconds(2), GROUP_PHASE_ALL);
- break;
- case EVENT_CHANGE_ORIENTATION:
- me->SetFacingTo(_orientation);
- break;
- case EVENT_FLY:
- ChangeOrientation(3.137039f);
- events.ScheduleEvent(EVENT_MOVE_TO_WARGLAIVE_POINT, Seconds(6), GROUP_PHASE_ALL);
- break;
- case EVENT_FLY_TO_RANDOM_PILLAR:
- {
- events.CancelEventGroup(GROUP_PHASE_2);
- _pillarIndex = urand(0, 3);
- me->GetMotionMaster()->MovePoint(POINT_RANDOM_PILLAR, IllidanPhase2Positions[_pillarIndex]);
- events.Repeat(Seconds(30));
- break;
- }
- case EVENT_FACE_MIDDLE:
- {
- float angle = me->GetAngle(IllidanMiddlePoint);
- me->SetFacingTo(angle);
- break;
- }
- case EVENT_EYE_BLAST:
- {
- events.CancelEvent(EVENT_DARK_BARRAGE);
- Position pos = IllidanDBTargetSpawnPositions[_pillarIndex];
- if (TempSummon* dbTarget = me->SummonCreature(NPC_ILLIDAN_DB_TARGET, pos, TEMPSUMMON_MANUAL_DESPAWN))
- {
- Talk(SAY_ILLIDAN_EYE_BLAST);
- DoCast(dbTarget, SPELL_EYE_BLAST);
- dbTarget->GetMotionMaster()->MovePoint(POINT_DB_TARGET, IllidanDBTargetPoints[_pillarIndex]);
- }
- break;
- }
- case EVENT_DARK_BARRAGE:
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150.0f, true))
- DoCast(target, SPELL_DARK_BARRAGE);
- events.RescheduleEvent(EVENT_EYE_BLAST, Seconds(5), GROUP_PHASE_2);
- uint32 currentTime = events.GetNextEventTime(EVENT_FLY_TO_RANDOM_PILLAR);
- events.RescheduleEvent(EVENT_FLY_TO_RANDOM_PILLAR, Seconds(currentTime) + Seconds(30), GROUP_PHASE_2);
- break;
- }
- case EVENT_FIREBALL:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150.0f, true))
- DoCast(target, SPELL_FIREBALL);
- events.Repeat(Seconds(2), Seconds(4));
- break;
- case EVENT_GLAIVE_EMOTE:
- me->SetDisableGravity(false);
- me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
- me->SetSheath(SHEATH_STATE_MELEE);
- events.ScheduleEvent(EVENT_RESUME_COMBAT, Seconds(3), GROUP_PHASE_ALL);
- break;
- case EVENT_RESUME_COMBAT:
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetReactState(REACT_AGGRESSIVE);
- ScheduleEvents(GROUP_PHASE_3, GROUP_PHASE_3);
- if (GameObject* musicController = instance->GetGameObject(DATA_ILLIDAN_MUSIC_CONTROLLER))
- musicController->PlayDirectMusic(EVENT_BT_STORM_WALK_UNI_3_SOUND_ID);
- break;
- case EVENT_AGONIZING_FLAMES:
- DoCastSelf(SPELL_AGONIZING_FLAMES_SELECTOR);
- events.Repeat(Seconds(53));
- break;
- case EVENT_DEMON:
- me->SetControlled(true, UNIT_STATE_ROOT);
- _isDemon = true;
- events.CancelEventGroup(_phase == PHASE_3 ? GROUP_PHASE_3 : GROUP_PHASE_4);
- me->LoadEquipment(0, true);
- DoCastSelf(SPELL_DEMON_TRANSFORM_1, true);
- events.ScheduleEvent(EVENT_DEMON_TEXT, Seconds(2), GROUP_PHASE_ALL);
- specialEvents.ScheduleEvent(EVENT_CANCEL_DEMON_FORM, Minutes(1) + Seconds(12));
- events.ScheduleEvent(EVENT_SCHEDULE_DEMON_SPELLS, Seconds(15));
- break;
- case EVENT_SCHEDULE_DEMON_SPELLS:
- ResetThreatList();
- ScheduleEvents(GROUP_PHASE_DEMON, GROUP_PHASE_DEMON);
- break;
- case EVENT_DEMON_TEXT:
- Talk(SAY_ILLIDAN_MORPH);
- break;
- case EVENT_RESUME_COMBAT_DEMON:
- {
- uint8 group = _phase == PHASE_3 ? GROUP_PHASE_3 : GROUP_PHASE_4;
- ResetThreatList();
- ScheduleEvents(group, group);
- me->LoadEquipment(1, true);
- break;
- }
- case EVENT_FLAME_BURST:
- DoCastSelf(SPELL_FLAME_BURST);
- events.Repeat(Seconds(22));
- break;
- case EVENT_SHADOW_DEMON:
- DoCastSelf(SPELL_SUMMON_SHADOWDEMON);
- break;
- case EVENT_SHADOW_BLAST:
- DoCastVictim(SPELL_SHADOW_BLAST);
- events.Repeat(Seconds(2));
- break;
- case EVENT_PHASE_4_DELAYED:
- DoAction(ACTION_START_PHASE_4);
- break;
- case EVENT_SHADOW_PRISON_TEXT:
- Talk(SAY_ILLIDAN_SHADOW_PRISON);
- events.ScheduleEvent(EVENT_SUMMON_MAIEV, Seconds(9), GROUP_PHASE_ALL);
- break;
- case EVENT_SUMMON_MAIEV:
- DoCastSelf(SPELL_SUMMON_MAIEV);
- if (Creature* maiev = instance->GetCreature(DATA_MAIEV))
- me->SetFacingToObject(maiev);
- events.ScheduleEvent(EVENT_CONFRONT_MAIEV_TEXT, Seconds(9), GROUP_PHASE_ALL);
- break;
- case EVENT_CONFRONT_MAIEV_TEXT:
- Talk(SAY_ILLIDAN_CONFRONT_MAIEV);
- events.ScheduleEvent(EVENT_RESUME_COMBAT_PHASE_4, Seconds(13), GROUP_PHASE_ALL);
- break;
- case EVENT_RESUME_COMBAT_PHASE_4:
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetReactState(REACT_AGGRESSIVE);
- ScheduleEvents(GROUP_PHASE_4, GROUP_PHASE_4);
- break;
- case EVENT_FRENZY:
- DoCastSelf(SPELL_FRENZY);
- Talk(SAY_ILLIDAN_FRENZY);
- events.Repeat(Seconds(40));
- break;
- case EVENT_TAUNT:
- Talk(SAY_ILLIDAN_TAUNT);
- events.Repeat(Seconds(30), Seconds(60));
- break;
- case EVENT_DEFEATED_TEXT:
- Talk(SAY_ILLIDAN_DEFEATED);
- if (GameObject* musicController = instance->GetGameObject(DATA_ILLIDAN_MUSIC_CONTROLLER))
- musicController->PlayDirectMusic(EVENT_BT_ARRIVAL_WALK_HERO_1_SOUND_ID);
- events.ScheduleEvent(EVENT_QUIET_SUICIDE, Seconds(18));
- break;
- case EVENT_QUIET_SUICIDE:
- {
- DoCastSelf(SPELL_QUIET_SUICIDE, true);
- if (Creature* akama = instance->GetCreature(DATA_AKAMA))
- akama->AI()->DoAction(ACTION_START_OUTRO);
- ObjectGuid _akamaGUID = instance->GetGuidData(DATA_AKAMA);
- ObjectGuid _maievGUID = instance->GetGuidData(DATA_MAIEV);
- summons.DespawnIf([_akamaGUID, _maievGUID](ObjectGuid unitGuid)
- {
- return unitGuid != _akamaGUID && unitGuid != _maievGUID;
- });
- break;
- }
- default:
- break;
- }
+ void Reset() override
+ {
+ _events.Reset();
+ _spiritOfUdaloGUID.Clear();
+ _spiritOfOlumGUID.Clear();
+ _isTeleportToMinions = false;
+ }
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- }
+ bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
+ {
+ if (gossipListId == GOSSIP_START_INTRO)
+ {
+ _instance->SetData(DATA_AKAMA, AKAMA_FIGHT);
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_STAIRS, SPLINE_STAIRS, false);
+ me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
+ illidan->AI()->DoAction(ACTION_INTRO_DONE);
+ CloseGossipMenuFor(player);
- DoMeleeAttackIfReady();
}
+ else if (gossipListId == GOSSIP_START_FIGHT)
+ {
+ _events.SetPhase(PHASE_INTRO);
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_FACE_ILLIDAN, SPLINE_FACE_ILLIDAN, false);
+ me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ CloseGossipMenuFor(player);
+ }
+ return false;
+ }
- private:
- bool _intro;
- uint8 _minionsCount;
- uint8 _flameCount;
- float _orientation;
- uint8 _pillarIndex;
- uint8 _phase;
- bool _dead;
- bool _isDemon;
- EventMap specialEvents;
- };
+ bool CanAIAttack(Unit const* who) const override
+ {
+ if (_events.IsInPhase(PHASE_MINIONS) && who->GetEntry() == NPC_ILLIDAN_STORMRAGE)
+ return false;
+ return ScriptedAI::CanAIAttack(who);
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ uint32 GetData(uint32 /*data*/) const override
{
- return GetBlackTempleAI<boss_illidan_stormrageAI>(creature);
+ return _isTeleportToMinions ? 1 : 0;
}
-};
-class npc_akama : public CreatureScript
-{
-public:
- npc_akama() : CreatureScript("npc_akama_illidan") { }
+ void EnterEvadeMode(EvadeReason /*why*/) override { }
- struct npc_akamaAI : public ScriptedAI
+ void JustSummoned(Creature* summon) override
{
- npc_akamaAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _orientation(0.0f), _isTeleportToMinions(false) { }
-
- void Reset() override
+ if (summon->GetEntry() == NPC_SPIRIT_OF_UDALO)
{
- _events.Reset();
- _spiritOfUdaloGUID.Clear();
- _spiritOfOlumGUID.Clear();
- _isTeleportToMinions = false;
+ _spiritOfUdaloGUID = summon->GetGUID();
+ summon->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
}
-
- bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
+ else if (summon->GetEntry() == NPC_SPIRIT_OF_OLUM)
{
- if (gossipListId == GOSSIP_START_INTRO)
- {
- _instance->SetData(DATA_AKAMA, AKAMA_FIGHT);
- me->GetMotionMaster()->MoveAlongSplineChain(POINT_STAIRS, SPLINE_STAIRS, false);
- me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
- if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
- illidan->AI()->DoAction(ACTION_INTRO_DONE);
- CloseGossipMenuFor(player);
+ _spiritOfOlumGUID = summon->GetGUID();
+ summon->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ }
+ }
- }
- else if (gossipListId == GOSSIP_START_FIGHT)
- {
+ void DoAction(int32 actionId) override
+ {
+ switch (actionId)
+ {
+ case ACTION_ACTIVE_AKAMA_INTRO:
_events.SetPhase(PHASE_INTRO);
- me->GetMotionMaster()->MoveAlongSplineChain(POINT_FACE_ILLIDAN, SPLINE_FACE_ILLIDAN, false);
me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
- CloseGossipMenuFor(player);
- }
- return false;
+ _events.SetPhase(PHASE_INTRO);
+ _events.ScheduleEvent(EVENT_TELEPORT, Seconds(1));
+ _events.ScheduleEvent(EVENT_MOVE_TO_ILLIDARI_ROOM, Seconds(1) + Milliseconds(500));
+ break;
+ case ACTION_OPEN_DOOR:
+ _instance->SetData(ACTION_OPEN_DOOR, 0);
+ _events.ScheduleEvent(EVENT_AKAMA_THANKS, Seconds(2));
+ break;
+ case ACTION_FREE:
+ _events.ScheduleEvent(EVENT_FREE, Seconds(14));
+ break;
+ case ACTION_START_ENCOUNTER:
+ DoZoneInCombat();
+ _events.ScheduleEvent(EVENT_HEALING_POTION, Seconds(1));
+ break;
+ case ACTION_START_MINIONS:
+ _events.ScheduleEvent(EVENT_AKAMA_MINIONS, Seconds(8));
+ break;
+ case ACTION_START_OUTRO:
+ me->SetReactState(REACT_PASSIVE);
+ me->AttackStop();
+ _events.Reset();
+ _events.ScheduleEvent(EVENT_AKAMA_MOVE_BACK, Seconds(2));
+ break;
+ default:
+ break;
}
+ }
- bool CanAIAttack(Unit const* who) const override
- {
- if (_events.IsInPhase(PHASE_MINIONS) && who->GetEntry() == NPC_ILLIDAN_STORMRAGE)
- return false;
- return ScriptedAI::CanAIAttack(who);
- }
+ void ChangeOrientation(float orientation)
+ {
+ _orientation = orientation;
+ _events.ScheduleEvent(EVENT_CHANGE_ORIENTATION, Milliseconds(1));
+ }
- uint32 GetData(uint32 /*data*/) const override
- {
- return _isTeleportToMinions ? 1 : 0;
+ void MovementInform(uint32 type, uint32 pointId) override
+ {
+ if (type != POINT_MOTION_TYPE && type != SPLINE_CHAIN_MOTION_TYPE)
+ return;
+
+ switch (pointId)
+ {
+ case POINT_ILLIDARI_COUNCIL:
+ Talk(SAY_AKAMA_FINISH);
+ me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ break;
+ case POINT_STAIRS:
+ ChangeOrientation(6.265732f);
+ _events.ScheduleEvent(EVENT_AKAMA_SAY_DOOR, Seconds(5));
+ break;
+ case POINT_ILLIDAN_ROOM:
+ ChangeOrientation(2.129302f);
+ Talk(SAY_AKAMA_BETRAYER);
+ me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ break;
+ case POINT_FACE_ILLIDAN:
+ ChangeOrientation(3.140537f);
+ _events.ScheduleEvent(EVENT_START_ILLIDAN, Seconds(2));
+ break;
+ case POINT_TELEPORT:
+ DoCastSelf(SPELL_AKAMA_TELEPORT);
+ _events.ScheduleEvent(EVENT_AKAMA_MINIONS_MOVE_2, Milliseconds(500));
+ break;
+ case POINT_MINIONS:
+ _events.SetPhase(PHASE_MINIONS);
+ me->SetImmuneToNPC(false);
+ me->SetReactState(REACT_AGGRESSIVE);
+ if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
+ illidan->AI()->DoAction(ACTION_START_MINIONS_WEAVE);
+ _events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, Seconds(2));
+ break;
+ case POINT_MOVE_BACK:
+ _events.ScheduleEvent(EVENT_AKAMA_MOVE_TO_ILLIDAN, Milliseconds(1));
+ break;
+ case POINT_ILLIDAN:
+ _events.ScheduleEvent(EVENT_AKAMA_LIGHT_TEXT, Seconds(1));
+ break;
+ default:
+ break;
}
+ }
- void EnterEvadeMode(EvadeReason /*why*/) override { }
+ void DamageTaken(Unit* /*who*/, uint32 &damage) override
+ {
+ if (damage >= me->GetHealth())
+ damage = me->GetHealth() - 1;
+ }
- void JustSummoned(Creature* summon) override
- {
- if (summon->GetEntry() == NPC_SPIRIT_OF_UDALO)
- {
- _spiritOfUdaloGUID = summon->GetGUID();
- summon->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
- }
- else if (summon->GetEntry() == NPC_SPIRIT_OF_OLUM)
- {
- _spiritOfOlumGUID = summon->GetGUID();
- summon->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
- }
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim() && !_events.IsInPhase(PHASE_INTRO))
+ return;
+
+ _events.Update(diff);
- void DoAction(int32 actionId) override
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = _events.ExecuteEvent())
{
- switch (actionId)
+ switch (eventId)
{
- case ACTION_ACTIVE_AKAMA_INTRO:
- _events.SetPhase(PHASE_INTRO);
- me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
- _events.SetPhase(PHASE_INTRO);
- _events.ScheduleEvent(EVENT_TELEPORT, Seconds(1));
- _events.ScheduleEvent(EVENT_MOVE_TO_ILLIDARI_ROOM, Seconds(1) + Milliseconds(500));
+ case EVENT_TELEPORT:
+ DoCastSelf(SPELL_AKAMA_TELEPORT, true);
break;
- case ACTION_OPEN_DOOR:
- _instance->SetData(ACTION_OPEN_DOOR, 0);
- _events.ScheduleEvent(EVENT_AKAMA_THANKS, Seconds(2));
+ case EVENT_MOVE_TO_ILLIDARI_ROOM:
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_ILLIDARI_COUNCIL, SPLINE_ILLIDARI_COUNCIL, false);
break;
- case ACTION_FREE:
- _events.ScheduleEvent(EVENT_FREE, Seconds(14));
+ case EVENT_AKAMA_SAY_DOOR:
+ Talk(SAY_AKAMA_DOOR);
+ _events.ScheduleEvent(EVENT_AKAMA_DOOR_FAIL, Seconds(4));
break;
- case ACTION_START_ENCOUNTER:
- DoZoneInCombat();
- _events.ScheduleEvent(EVENT_HEALING_POTION, Seconds(1));
+ case EVENT_AKAMA_DOOR_FAIL:
+ DoCastSelf(SPELL_AKAMA_DOOR_FAIL);
+ _events.ScheduleEvent(EVENT_AKAMA_SAY_ALONE, Seconds(10));
+ break;
+ case EVENT_AKAMA_SAY_ALONE:
+ Talk(SAY_AKAMA_ALONE);
+ _events.ScheduleEvent(EVENT_SUMMON_SPIRITS, Seconds(7));
+ break;
+ case EVENT_SUMMON_SPIRITS:
+ me->SummonCreatureGroup(SUMMON_GROUP);
+ _events.ScheduleEvent(EVENT_SPIRIT_SAY_1, Seconds(1));
+ break;
+ case EVENT_SPIRIT_SAY_1:
+ if (Creature* undalo = ObjectAccessor::GetCreature(*me, _spiritOfUdaloGUID))
+ undalo->AI()->Talk(SAY_SPIRIT_ALONE);
+ _events.ScheduleEvent(EVENT_SPIRIT_SAY_2, Seconds(6));
break;
- case ACTION_START_MINIONS:
- _events.ScheduleEvent(EVENT_AKAMA_MINIONS, Seconds(8));
+ case EVENT_SPIRIT_SAY_2:
+ if (Creature* olum = ObjectAccessor::GetCreature(*me, _spiritOfOlumGUID))
+ olum->AI()->Talk(SAY_SPIRIT_ALONE);
+ _events.ScheduleEvent(EVENT_AKAMA_DOOR_SUCCESS, Seconds(6));
break;
- case ACTION_START_OUTRO:
+ case EVENT_AKAMA_DOOR_SUCCESS:
+ DoCastSelf(SPELL_AKAMA_DOOR_CHANNEL);
+ if (Creature* undalo = ObjectAccessor::GetCreature(*me, _spiritOfUdaloGUID))
+ undalo->CastSpell((Unit*) nullptr, SPELL_DEATHSWORN_DOOR_CHANNEL);
+ if (Creature* olum = ObjectAccessor::GetCreature(*me, _spiritOfOlumGUID))
+ olum->CastSpell((Unit*) nullptr, SPELL_DEATHSWORN_DOOR_CHANNEL);
+ _events.ScheduleEvent(EVENT_AKAMA_START_SOUND, Seconds(5));
+ break;
+ case EVENT_AKAMA_START_SOUND:
+ if (GameObject* musicController = _instance->GetGameObject(DATA_ILLIDAN_MUSIC_CONTROLLER))
+ musicController->PlayDirectMusic(EVENT_BT_SUMMIT_WALK_SOUND_ID);
+ break;
+ case EVENT_AKAMA_THANKS:
+ Talk(SAY_AKAMA_SALUTE);
+ _events.ScheduleEvent(EVENT_SPIRIT_SALUTE, Seconds(3));
+ _events.ScheduleEvent(EVENT_RUN_FROM_ILLIDAN_ROOM, Seconds(7));
+ break;
+ case EVENT_SPIRIT_SALUTE:
+ if (Creature* undalo = ObjectAccessor::GetCreature(*me, _spiritOfUdaloGUID))
+ {
+ undalo->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE);
+ undalo->DespawnOrUnsummon(Seconds(7));
+ }
+ if (Creature* olum = ObjectAccessor::GetCreature(*me, _spiritOfOlumGUID))
+ {
+ olum->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE);
+ olum->DespawnOrUnsummon(Seconds(7));
+ }
+ break;
+ case EVENT_RUN_FROM_ILLIDAN_ROOM:
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_ILLIDAN_ROOM, SPLINE_ILLIDAN_ROOM, false);
+ break;
+ case EVENT_START_ILLIDAN:
+ if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
+ illidan->AI()->DoAction(ACTION_START_ENCOUNTER);
+ break;
+ case EVENT_FREE:
+ Talk(SAY_AKAMA_FREE);
+ _events.ScheduleEvent(EVENT_TIME_HAS_COME, Seconds(18));
+ break;
+ case EVENT_TIME_HAS_COME:
+ Talk(SAY_AKAMA_TIME_HAS_COME);
+ _events.ScheduleEvent(EVENT_ROAR, Seconds(2));
+ break;
+ case EVENT_ROAR:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR);
+ me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY1H);
+ break;
+ case EVENT_CHANGE_ORIENTATION:
+ me->SetFacingTo(_orientation);
+ break;
+ case EVENT_HEALING_POTION:
+ if (me->HealthBelowPct(20))
+ DoCastSelf(SPELL_HEALING_POTION);
+ _events.Repeat(Seconds(1));
+ break;
+ case EVENT_AKAMA_MINIONS:
+ Talk(SAY_AKAMA_MINIONS);
+ _events.ScheduleEvent(EVENT_AKAMA_MINIONS_EMOTE, Seconds(2));
+ break;
+ case EVENT_AKAMA_MINIONS_EMOTE:
me->SetReactState(REACT_PASSIVE);
me->AttackStop();
- _events.Reset();
- _events.ScheduleEvent(EVENT_AKAMA_MOVE_BACK, Seconds(2));
+ me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION);
+ me->SetImmuneToNPC(true);
+ _events.ScheduleEvent(EVENT_AKAMA_MINIONS_MOVE, Seconds(4));
break;
- default:
+ case EVENT_AKAMA_MINIONS_MOVE:
+ _isTeleportToMinions = true;
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_TELEPORT, SPLINE_TELEPORT, false);
break;
- }
- }
-
- void ChangeOrientation(float orientation)
- {
- _orientation = orientation;
- _events.ScheduleEvent(EVENT_CHANGE_ORIENTATION, Milliseconds(1));
- }
-
- void MovementInform(uint32 type, uint32 pointId) override
- {
- if (type != POINT_MOTION_TYPE && type != SPLINE_CHAIN_MOTION_TYPE)
- return;
-
- switch (pointId)
- {
- case POINT_ILLIDARI_COUNCIL:
- Talk(SAY_AKAMA_FINISH);
- me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
- break;
- case POINT_STAIRS:
- ChangeOrientation(6.265732f);
- _events.ScheduleEvent(EVENT_AKAMA_SAY_DOOR, Seconds(5));
- break;
- case POINT_ILLIDAN_ROOM:
- ChangeOrientation(2.129302f);
- Talk(SAY_AKAMA_BETRAYER);
- me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
- break;
- case POINT_FACE_ILLIDAN:
- ChangeOrientation(3.140537f);
- _events.ScheduleEvent(EVENT_START_ILLIDAN, Seconds(2));
- break;
- case POINT_TELEPORT:
- DoCastSelf(SPELL_AKAMA_TELEPORT);
- _events.ScheduleEvent(EVENT_AKAMA_MINIONS_MOVE_2, Milliseconds(500));
- break;
- case POINT_MINIONS:
- _events.SetPhase(PHASE_MINIONS);
- me->SetImmuneToNPC(false);
- me->SetReactState(REACT_AGGRESSIVE);
+ case EVENT_AKAMA_MINIONS_MOVE_2:
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_MINIONS, SPLINE_MINIONS, false);
+ break;
+ case EVENT_CHAIN_LIGHTNING:
+ DoCastVictim(SPELL_CHAIN_LIGHTNING);
+ _events.Repeat(Seconds(8) + Milliseconds(500));
+ break;
+ case EVENT_AKAMA_MOVE_BACK:
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_MOVE_BACK, SPLINE_MOVE_BACK, false);
+ break;
+ case EVENT_AKAMA_MOVE_TO_ILLIDAN:
if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
- illidan->AI()->DoAction(ACTION_START_MINIONS_WEAVE);
- _events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, Seconds(2));
+ me->GetMotionMaster()->MoveCloserAndStop(POINT_ILLIDAN, illidan, 5.0f);
+ break;
+ case EVENT_AKAMA_LIGHT_TEXT:
+ Talk(SAY_AKAMA_LIGHT);
+ _events.ScheduleEvent(EVENT_FINAL_SALUTE, Seconds(4));
break;
- case POINT_MOVE_BACK:
- _events.ScheduleEvent(EVENT_AKAMA_MOVE_TO_ILLIDAN, Milliseconds(1));
+ case EVENT_FINAL_SALUTE:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE);
+ _events.ScheduleEvent(EVENT_AKAMA_DESPAWN, Seconds(5));
break;
- case POINT_ILLIDAN:
- _events.ScheduleEvent(EVENT_AKAMA_LIGHT_TEXT, Seconds(1));
+ case EVENT_AKAMA_DESPAWN:
+ DoCastSelf(SPELL_AKAMA_DESPAWN, true);
break;
default:
break;
}
- }
-
- void DamageTaken(Unit* /*who*/, uint32 &damage) override
- {
- if (damage >= me->GetHealth())
- damage = me->GetHealth() - 1;
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim() && !_events.IsInPhase(PHASE_INTRO))
- return;
-
- _events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
-
- while (uint32 eventId = _events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_TELEPORT:
- DoCastSelf(SPELL_AKAMA_TELEPORT, true);
- break;
- case EVENT_MOVE_TO_ILLIDARI_ROOM:
- me->GetMotionMaster()->MoveAlongSplineChain(POINT_ILLIDARI_COUNCIL, SPLINE_ILLIDARI_COUNCIL, false);
- break;
- case EVENT_AKAMA_SAY_DOOR:
- Talk(SAY_AKAMA_DOOR);
- _events.ScheduleEvent(EVENT_AKAMA_DOOR_FAIL, Seconds(4));
- break;
- case EVENT_AKAMA_DOOR_FAIL:
- DoCastSelf(SPELL_AKAMA_DOOR_FAIL);
- _events.ScheduleEvent(EVENT_AKAMA_SAY_ALONE, Seconds(10));
- break;
- case EVENT_AKAMA_SAY_ALONE:
- Talk(SAY_AKAMA_ALONE);
- _events.ScheduleEvent(EVENT_SUMMON_SPIRITS, Seconds(7));
- break;
- case EVENT_SUMMON_SPIRITS:
- me->SummonCreatureGroup(SUMMON_GROUP);
- _events.ScheduleEvent(EVENT_SPIRIT_SAY_1, Seconds(1));
- break;
- case EVENT_SPIRIT_SAY_1:
- if (Creature* undalo = ObjectAccessor::GetCreature(*me, _spiritOfUdaloGUID))
- undalo->AI()->Talk(SAY_SPIRIT_ALONE);
- _events.ScheduleEvent(EVENT_SPIRIT_SAY_2, Seconds(6));
- break;
- case EVENT_SPIRIT_SAY_2:
- if (Creature* olum = ObjectAccessor::GetCreature(*me, _spiritOfOlumGUID))
- olum->AI()->Talk(SAY_SPIRIT_ALONE);
- _events.ScheduleEvent(EVENT_AKAMA_DOOR_SUCCESS, Seconds(6));
- break;
- case EVENT_AKAMA_DOOR_SUCCESS:
- DoCastSelf(SPELL_AKAMA_DOOR_CHANNEL);
- if (Creature* undalo = ObjectAccessor::GetCreature(*me, _spiritOfUdaloGUID))
- undalo->CastSpell((Unit*) nullptr, SPELL_DEATHSWORN_DOOR_CHANNEL);
- if (Creature* olum = ObjectAccessor::GetCreature(*me, _spiritOfOlumGUID))
- olum->CastSpell((Unit*) nullptr, SPELL_DEATHSWORN_DOOR_CHANNEL);
- _events.ScheduleEvent(EVENT_AKAMA_START_SOUND, Seconds(5));
- break;
- case EVENT_AKAMA_START_SOUND:
- if (GameObject* musicController = _instance->GetGameObject(DATA_ILLIDAN_MUSIC_CONTROLLER))
- musicController->PlayDirectMusic(EVENT_BT_SUMMIT_WALK_SOUND_ID);
- break;
- case EVENT_AKAMA_THANKS:
- Talk(SAY_AKAMA_SALUTE);
- _events.ScheduleEvent(EVENT_SPIRIT_SALUTE, Seconds(3));
- _events.ScheduleEvent(EVENT_RUN_FROM_ILLIDAN_ROOM, Seconds(7));
- break;
- case EVENT_SPIRIT_SALUTE:
- if (Creature* undalo = ObjectAccessor::GetCreature(*me, _spiritOfUdaloGUID))
- {
- undalo->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE);
- undalo->DespawnOrUnsummon(Seconds(7));
- }
- if (Creature* olum = ObjectAccessor::GetCreature(*me, _spiritOfOlumGUID))
- {
- olum->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE);
- olum->DespawnOrUnsummon(Seconds(7));
- }
- break;
- case EVENT_RUN_FROM_ILLIDAN_ROOM:
- me->GetMotionMaster()->MoveAlongSplineChain(POINT_ILLIDAN_ROOM, SPLINE_ILLIDAN_ROOM, false);
- break;
- case EVENT_START_ILLIDAN:
- if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
- illidan->AI()->DoAction(ACTION_START_ENCOUNTER);
- break;
- case EVENT_FREE:
- Talk(SAY_AKAMA_FREE);
- _events.ScheduleEvent(EVENT_TIME_HAS_COME, Seconds(18));
- break;
- case EVENT_TIME_HAS_COME:
- Talk(SAY_AKAMA_TIME_HAS_COME);
- _events.ScheduleEvent(EVENT_ROAR, Seconds(2));
- break;
- case EVENT_ROAR:
- me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR);
- me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY1H);
- break;
- case EVENT_CHANGE_ORIENTATION:
- me->SetFacingTo(_orientation);
- break;
- case EVENT_HEALING_POTION:
- if (me->HealthBelowPct(20))
- DoCastSelf(SPELL_HEALING_POTION);
- _events.Repeat(Seconds(1));
- break;
- case EVENT_AKAMA_MINIONS:
- Talk(SAY_AKAMA_MINIONS);
- _events.ScheduleEvent(EVENT_AKAMA_MINIONS_EMOTE, Seconds(2));
- break;
- case EVENT_AKAMA_MINIONS_EMOTE:
- me->SetReactState(REACT_PASSIVE);
- me->AttackStop();
- me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION);
- me->SetImmuneToNPC(true);
- _events.ScheduleEvent(EVENT_AKAMA_MINIONS_MOVE, Seconds(4));
- break;
- case EVENT_AKAMA_MINIONS_MOVE:
- _isTeleportToMinions = true;
- me->GetMotionMaster()->MoveAlongSplineChain(POINT_TELEPORT, SPLINE_TELEPORT, false);
- break;
- case EVENT_AKAMA_MINIONS_MOVE_2:
- me->GetMotionMaster()->MoveAlongSplineChain(POINT_MINIONS, SPLINE_MINIONS, false);
- break;
- case EVENT_CHAIN_LIGHTNING:
- DoCastVictim(SPELL_CHAIN_LIGHTNING);
- _events.Repeat(Seconds(8) + Milliseconds(500));
- break;
- case EVENT_AKAMA_MOVE_BACK:
- me->GetMotionMaster()->MoveAlongSplineChain(POINT_MOVE_BACK, SPLINE_MOVE_BACK, false);
- break;
- case EVENT_AKAMA_MOVE_TO_ILLIDAN:
- if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
- me->GetMotionMaster()->MoveCloserAndStop(POINT_ILLIDAN, illidan, 5.0f);
- break;
- case EVENT_AKAMA_LIGHT_TEXT:
- Talk(SAY_AKAMA_LIGHT);
- _events.ScheduleEvent(EVENT_FINAL_SALUTE, Seconds(4));
- break;
- case EVENT_FINAL_SALUTE:
- me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE);
- _events.ScheduleEvent(EVENT_AKAMA_DESPAWN, Seconds(5));
- break;
- case EVENT_AKAMA_DESPAWN:
- DoCastSelf(SPELL_AKAMA_DESPAWN, true);
- break;
- default:
- break;
- }
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- }
-
- DoMeleeAttackIfReady();
}
- private:
- InstanceScript* _instance;
- EventMap _events;
- ObjectGuid _spiritOfUdaloGUID;
- ObjectGuid _spiritOfOlumGUID;
- float _orientation;
- bool _isTeleportToMinions;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<npc_akamaAI>(creature);
+ DoMeleeAttackIfReady();
}
+
+private:
+ InstanceScript* _instance;
+ EventMap _events;
+ ObjectGuid _spiritOfUdaloGUID;
+ ObjectGuid _spiritOfOlumGUID;
+ float _orientation;
+ bool _isTeleportToMinions;
};
-class npc_parasitic_shadowfiend : public CreatureScript
+struct npc_parasitic_shadowfiend : public ScriptedAI
{
-public:
- npc_parasitic_shadowfiend() : CreatureScript("npc_parasitic_shadowfiend") { }
+ npc_parasitic_shadowfiend(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
- struct npc_parasitic_shadowfiendAI : public ScriptedAI
+ void Reset() override
{
- npc_parasitic_shadowfiendAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
+ if (_instance->GetBossState(DATA_ILLIDAN_STORMRAGE) != IN_PROGRESS)
+ {
+ me->DespawnOrUnsummon();
+ return;
+ }
- void Reset() override
+ if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
+ illidan->AI()->JustSummoned(me);
+ me->SetReactState(REACT_DEFENSIVE);
+ _scheduler.Schedule(Seconds(2), [this](TaskContext /*context*/)
{
- if (_instance->GetBossState(DATA_ILLIDAN_STORMRAGE) != IN_PROGRESS)
- {
- me->DespawnOrUnsummon();
- return;
- }
+ me->SetReactState(REACT_AGGRESSIVE);
+ me->SetInCombatWithZone();
+ });
+ }
- if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
- illidan->AI()->JustSummoned(me);
- me->SetReactState(REACT_DEFENSIVE);
+ void DoAction(int32 action) override
+ {
+ if (action == ACTION_START_PHASE_4)
+ {
+ me->SetReactState(REACT_PASSIVE);
+ me->AttackStop();
+ }
+ else if (action == ACTION_RESUME_COMBAT)
_scheduler.Schedule(Seconds(2), [this](TaskContext /*context*/)
{
me->SetReactState(REACT_AGGRESSIVE);
me->SetInCombatWithZone();
});
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ }
- _scheduler.Update(diff, [this]
- {
- DoMeleeAttackIfReady();
- });
- }
+ void UpdateAI(uint32 diff) override
+ {
+ _scheduler.Update(diff);
- private:
- InstanceScript* _instance;
- TaskScheduler _scheduler;
- };
+ if (!UpdateVictim())
+ return;
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<npc_parasitic_shadowfiendAI>(creature);
+ DoMeleeAttackIfReady();
}
+
+private:
+ InstanceScript* _instance;
+ TaskScheduler _scheduler;
};
-class npc_blade_of_azzinoth : public CreatureScript
+struct npc_blade_of_azzinoth : public NullCreatureAI
{
-public:
- npc_blade_of_azzinoth() : CreatureScript("npc_blade_of_azzinoth") { }
+ npc_blade_of_azzinoth(Creature* creature) : NullCreatureAI(creature), _instance(creature->GetInstanceScript()) { }
- struct npc_blade_of_azzinothAI : public NullCreatureAI
+ void Reset() override
{
- npc_blade_of_azzinothAI(Creature* creature) : NullCreatureAI(creature), _instance(creature->GetInstanceScript()) { }
-
- void Reset() override
- {
- if (_instance->GetBossState(DATA_ILLIDAN_STORMRAGE) != IN_PROGRESS)
- {
- me->DespawnOrUnsummon();
- return;
- }
-
- if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
- illidan->AI()->JustSummoned(me);
- _flameGuid.Clear();
- me->PlayDirectSound(WARGLAIVE_SPAWN_SOUND_ID);
- DoCastSelf(SPELL_BIRTH, true);
- _scheduler.Schedule(Seconds(3), [this](TaskContext /*context*/)
- {
- DoCastSelf(SPELL_SUMMON_TEAR_OF_AZZINOTH);
- _scheduler.Schedule(Milliseconds(500), [this](TaskContext /*context*/)
- {
- if (Creature* flame = ObjectAccessor::GetCreature(*me, _flameGuid))
- DoCast(flame, SPELL_AZZINOTH_CHANNEL);
- });
- });
- }
-
- void JustSummoned(Creature* summon) override
+ if (_instance->GetBossState(DATA_ILLIDAN_STORMRAGE) != IN_PROGRESS)
{
- if (summon->GetEntry() == NPC_FLAME_OF_AZZINOTH)
- _flameGuid = summon->GetGUID();
+ me->DespawnOrUnsummon();
+ return;
}
- void UpdateAI(uint32 diff) override
+ if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
+ illidan->AI()->JustSummoned(me);
+ _flameGuid.Clear();
+ me->PlayDirectSound(WARGLAIVE_SPAWN_SOUND_ID);
+ DoCastSelf(SPELL_BIRTH, true);
+ _scheduler.Schedule(Seconds(3), [this](TaskContext /*context*/)
{
- _scheduler.Update(diff);
- }
+ DoCastSelf(SPELL_SUMMON_TEAR_OF_AZZINOTH);
+ _scheduler.Schedule(Milliseconds(500), [this](TaskContext /*context*/)
+ {
+ if (Creature* flame = ObjectAccessor::GetCreature(*me, _flameGuid))
+ DoCast(flame, SPELL_AZZINOTH_CHANNEL);
+ });
+ });
+ }
- private:
- InstanceScript* _instance;
- TaskScheduler _scheduler;
- ObjectGuid _flameGuid;
- };
+ void JustSummoned(Creature* summon) override
+ {
+ if (summon->GetEntry() == NPC_FLAME_OF_AZZINOTH)
+ _flameGuid = summon->GetGUID();
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void UpdateAI(uint32 diff) override
{
- return GetBlackTempleAI<npc_blade_of_azzinothAI>(creature);
+ _scheduler.Update(diff);
}
+
+private:
+ InstanceScript* _instance;
+ TaskScheduler _scheduler;
+ ObjectGuid _flameGuid;
};
-class npc_flame_of_azzinoth : public CreatureScript
+struct npc_flame_of_azzinoth : public ScriptedAI
{
-public:
- npc_flame_of_azzinoth() : CreatureScript("npc_flame_of_azzinoth") { }
+ npc_flame_of_azzinoth(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript())
+ {
+ SetBoundary(_instance->GetBossBoundary(DATA_ILLIDAN_STORMRAGE));
+ }
- struct npc_flame_of_azzinothAI : public ScriptedAI
+ void Reset() override
{
- npc_flame_of_azzinothAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript())
+ if (_instance->GetBossState(DATA_ILLIDAN_STORMRAGE) != IN_PROGRESS)
{
- SetBoundary(_instance->GetBossBoundary(DATA_ILLIDAN_STORMRAGE));
+ me->DespawnOrUnsummon();
+ return;
}
- void Reset() override
- {
- if (_instance->GetBossState(DATA_ILLIDAN_STORMRAGE) != IN_PROGRESS)
- {
- me->DespawnOrUnsummon();
- return;
- }
-
- if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
- illidan->AI()->JustSummoned(me);
- DoCastSelf(SPELL_FLAME_TEAR_OF_AZZINOTH, true); // Idk what this spell should do
- me->SetReactState(REACT_PASSIVE);
- _events.ScheduleEvent(EVENT_ENGAGE, Seconds(3));
- _events.ScheduleEvent(EVENT_FLAME_BLAST, Seconds(11));
- }
+ if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
+ illidan->AI()->JustSummoned(me);
+ DoCastSelf(SPELL_FLAME_TEAR_OF_AZZINOTH, true); // Idk what this spell should do
+ me->SetReactState(REACT_PASSIVE);
+ _events.ScheduleEvent(EVENT_ENGAGE, Seconds(3));
+ _events.ScheduleEvent(EVENT_FLAME_BLAST, Seconds(11));
+ }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- _events.Update(diff);
+ _events.Update(diff);
- while (uint32 eventId = _events.ExecuteEvent())
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
{
- switch (eventId)
- {
- case EVENT_ENGAGE:
- me->SetReactState(REACT_AGGRESSIVE);
- me->SetInCombatWithZone();
- _events.ScheduleEvent(EVENT_FLAME_CHARGE, Seconds(5));
- break;
- case EVENT_FLAME_CHARGE:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, ChargeTargetSelector(me)))
- {
- DoCast(target, SPELL_CHARGE);
- _events.Repeat(Seconds(5));
- }
- else
- _events.Repeat(Seconds(1));
- break;
- case EVENT_FLAME_BLAST:
- DoCastAOE(SPELL_FLAME_BLAST);
- _events.Repeat(Seconds(12));
- break;
- default:
- break;
- }
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ case EVENT_ENGAGE:
+ me->SetReactState(REACT_AGGRESSIVE);
+ me->SetInCombatWithZone();
+ _events.ScheduleEvent(EVENT_FLAME_CHARGE, Seconds(5));
+ break;
+ case EVENT_FLAME_CHARGE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, ChargeTargetSelector()))
+ {
+ DoCast(target, SPELL_CHARGE);
+ _events.Repeat(Seconds(5));
+ }
+ else
+ _events.Repeat(Seconds(1));
+ break;
+ case EVENT_FLAME_BLAST:
+ DoCastAOE(SPELL_FLAME_BLAST);
+ _events.Repeat(Seconds(12));
+ break;
+ default:
+ break;
}
- DoMeleeAttackIfReady();
- }
-
- void JustDied(Unit* /*killer*/) override
- {
- if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
- illidan->AI()->DoAction(ACTION_FLAME_DEAD);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
- private:
- InstanceScript* _instance;
- EventMap _events;
- };
+ DoMeleeAttackIfReady();
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void JustDied(Unit* /*killer*/) override
{
- return GetBlackTempleAI<npc_flame_of_azzinothAI>(creature);
+ if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
+ illidan->AI()->DoAction(ACTION_FLAME_DEAD);
}
+
+private:
+ InstanceScript* _instance;
+ EventMap _events;
};
-class npc_illidan_db_target : public CreatureScript
+struct npc_illidan_db_target : public NullCreatureAI
{
-public:
- npc_illidan_db_target() : CreatureScript("npc_illidan_db_target") { }
+ npc_illidan_db_target(Creature* creature) : NullCreatureAI(creature) { }
- struct npc_illidan_db_targetAI : public NullCreatureAI
+ void Reset() override
{
- npc_illidan_db_targetAI(Creature* creature) : NullCreatureAI(creature) { }
-
- void Reset() override
- {
- DoCastSelf(SPELL_EYE_BLAST_TRIGGER);
- }
+ DoCastSelf(SPELL_EYE_BLAST_TRIGGER);
+ }
- void JustSummoned(Creature* summon) override
- {
- if (summon->GetEntry() == NPC_DEMON_FIRE)
- summon->SetReactState(REACT_PASSIVE);
- }
+ void JustSummoned(Creature* summon) override
+ {
+ if (summon->GetEntry() == NPC_DEMON_FIRE)
+ summon->SetReactState(REACT_PASSIVE);
+ }
- void MovementInform(uint32 type, uint32 pointId) override
+ void MovementInform(uint32 type, uint32 pointId) override
+ {
+ if (type == POINT_MOTION_TYPE && pointId == POINT_DB_TARGET)
{
- if (type == POINT_MOTION_TYPE && pointId == POINT_DB_TARGET)
- {
- me->RemoveAurasDueToSpell(SPELL_EYE_BLAST_TRIGGER);
- me->RemoveAurasDueToSpell(SPELL_EYE_BLAST);
- }
+ me->RemoveAurasDueToSpell(SPELL_EYE_BLAST_TRIGGER);
+ me->RemoveAurasDueToSpell(SPELL_EYE_BLAST);
}
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<npc_illidan_db_targetAI>(creature);
}
};
-class npc_illidan_shadow_demon : public CreatureScript
+struct npc_shadow_demon : public PassiveAI
{
-public:
- npc_illidan_shadow_demon() : CreatureScript("npc_shadow_demon") { }
+ npc_shadow_demon(Creature* creature) : PassiveAI(creature), _instance(creature->GetInstanceScript()) { }
- struct npc_illidan_shadow_demonAI : public PassiveAI
+ void Reset() override
{
- npc_illidan_shadow_demonAI(Creature* creature) : PassiveAI(creature), _instance(creature->GetInstanceScript()) { }
-
- void Reset() override
+ if (_instance->GetBossState(DATA_ILLIDAN_STORMRAGE) != IN_PROGRESS)
{
- if (_instance->GetBossState(DATA_ILLIDAN_STORMRAGE) != IN_PROGRESS)
- {
- me->DespawnOrUnsummon();
- return;
- }
-
- DoCastSelf(SPELL_SHADOW_DEMON_PASSIVE);
- DoCastSelf(SPELL_FIND_TARGET);
- _scheduler.Schedule(Seconds(1), [this](TaskContext checkTarget)
- {
- if (Unit* target = ObjectAccessor::GetUnit(*me, _targetGUID))
- {
- if (!target->IsAlive())
- DoCastSelf(SPELL_FIND_TARGET);
- else if (me->IsWithinMeleeRange(target))
- {
- me->InterruptNonMeleeSpells(false);
- DoCast(target, SPELL_CONSUME_SOUL, true);
- }
- }
- checkTarget.Repeat();
- });
+ me->DespawnOrUnsummon();
+ return;
}
- void SetGUID(ObjectGuid guid, int32 /*id*/) override
+ DoCastSelf(SPELL_SHADOW_DEMON_PASSIVE);
+ DoCastSelf(SPELL_FIND_TARGET);
+ _scheduler.Schedule(Seconds(1), [this](TaskContext checkTarget)
{
- _targetGUID = guid;
if (Unit* target = ObjectAccessor::GetUnit(*me, _targetGUID))
- me->GetMotionMaster()->MoveChase(target);
- }
-
- void UpdateAI(uint32 diff) override
- {
- _scheduler.Update(diff);
- }
+ {
+ if (!target->IsAlive())
+ DoCastSelf(SPELL_FIND_TARGET);
+ else if (me->IsWithinMeleeRange(target))
+ {
+ me->InterruptNonMeleeSpells(false);
+ DoCast(target, SPELL_CONSUME_SOUL, true);
+ }
+ }
+ checkTarget.Repeat();
+ });
+ }
- private:
- InstanceScript* _instance;
- TaskScheduler _scheduler;
- ObjectGuid _targetGUID;
- };
+ void SetGUID(ObjectGuid guid, int32 /*id*/) override
+ {
+ _targetGUID = guid;
+ if (Unit* target = ObjectAccessor::GetUnit(*me, _targetGUID))
+ me->GetMotionMaster()->MoveChase(target);
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void UpdateAI(uint32 diff) override
{
- return GetBlackTempleAI<npc_illidan_shadow_demonAI>(creature);
+ _scheduler.Update(diff);
}
+
+private:
+ InstanceScript* _instance;
+ TaskScheduler _scheduler;
+ ObjectGuid _targetGUID;
};
-class npc_maiev : public CreatureScript
+struct npc_maiev : public ScriptedAI
{
-public:
- npc_maiev() : CreatureScript("npc_maiev") { }
+ npc_maiev(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _canDown(true) { }
+
+ void Reset() override
+ {
+ if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
+ me->SetFacingToObject(illidan);
+ me->SetReactState(REACT_PASSIVE);
+ _events.SetPhase(PHASE_INTRO);
+ _events.ScheduleEvent(EVENT_MAIEV_APPEAR, Seconds(1));
+ _events.ScheduleEvent(EVENT_MAIEV_EXCLAMATION, Seconds(2));
+ _events.ScheduleEvent(EVENT_MAIEV_JUSTICE_TEXT, Seconds(14));
+ _events.ScheduleEvent(EVENT_TAUNT, Seconds(20), Seconds(60));
+ _canDown = true;
+ }
- struct npc_maievAI : public ScriptedAI
+ void EnterCombat(Unit* /*who*/) override
{
- npc_maievAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _canDown(true) { }
+ _events.SetPhase(PHASE_1);
+ _events.ScheduleEvent(EVENT_CAGE_TRAP, Seconds(30));
+ _events.ScheduleEvent(EVENT_SHADOW_STRIKE, Seconds(50));
+ _events.ScheduleEvent(EVENT_THROW_DAGGER, Seconds(1));
+ }
- void Reset() override
+ void DoAction(int32 actionId) override
+ {
+ if (actionId == ACTION_START_OUTRO)
{
+ _events.Reset();
+ me->SetReactState(REACT_PASSIVE);
+ me->AttackStop();
if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
me->SetFacingToObject(illidan);
- me->SetReactState(REACT_PASSIVE);
- _events.SetPhase(PHASE_INTRO);
- _events.ScheduleEvent(EVENT_MAIEV_APPEAR, Seconds(1));
- _events.ScheduleEvent(EVENT_MAIEV_EXCLAMATION, Seconds(2));
- _events.ScheduleEvent(EVENT_MAIEV_JUSTICE_TEXT, Seconds(14));
- _events.ScheduleEvent(EVENT_TAUNT, Seconds(20), Seconds(60));
- _canDown = true;
+ Talk(SAY_MAIEV_SHADOWSONG_FINISHED);
+ _events.ScheduleEvent(EVENT_MAIEV_OUTRO_TEXT, Seconds(28));
}
+ else if (actionId == ACTION_MAIEV_DOWN_FADE)
+ _canDown = true;
+ }
- void EnterCombat(Unit* /*who*/) override
+ void DamageTaken(Unit* /*who*/, uint32 &damage) override
+ {
+ if (damage >= me->GetHealth() && _canDown)
{
- _events.SetPhase(PHASE_1);
- _events.ScheduleEvent(EVENT_CAGE_TRAP, Seconds(30));
- _events.ScheduleEvent(EVENT_SHADOW_STRIKE, Seconds(50));
- _events.ScheduleEvent(EVENT_THROW_DAGGER, Seconds(1));
+ damage = me->GetHealth() - 1;
+ _canDown = false;
+ DoCastSelf(SPELL_MAIEV_DOWN, true);
+ Talk(SAY_MAIEV_SHADOWSONG_DOWN, me);
}
+ }
- void DoAction(int32 actionId) override
- {
- if (actionId == ACTION_START_OUTRO)
- {
- _events.Reset();
- me->SetReactState(REACT_PASSIVE);
- me->AttackStop();
- if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
- me->SetFacingToObject(illidan);
- Talk(SAY_MAIEV_SHADOWSONG_FINISHED);
- _events.ScheduleEvent(EVENT_MAIEV_OUTRO_TEXT, Seconds(28));
- }
- else if (actionId == ACTION_MAIEV_DOWN_FADE)
- _canDown = true;
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim() && !_events.IsInPhase(PHASE_INTRO))
+ return;
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ _events.Update(diff);
- void DamageTaken(Unit* /*who*/, uint32 &damage) override
+ while (uint32 eventId = _events.ExecuteEvent())
{
- if (damage >= me->GetHealth() && _canDown)
+ switch (eventId)
{
- damage = me->GetHealth() - 1;
- _canDown = false;
- DoCastSelf(SPELL_MAIEV_DOWN, true);
- Talk(SAY_MAIEV_SHADOWSONG_DOWN, me);
+ case EVENT_MAIEV_APPEAR:
+ Talk(SAY_MAIEV_SHADOWSONG_APPEAR);
+ break;
+ case EVENT_MAIEV_EXCLAMATION:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION);
+ break;
+ case EVENT_MAIEV_JUSTICE_TEXT:
+ Talk(SAY_MAIEV_SHADOWSONG_JUSTICE);
+ _events.ScheduleEvent(EVENT_MAIEV_YES, Seconds(2));
+ break;
+ case EVENT_MAIEV_YES:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_YES);
+ _events.ScheduleEvent(EVENT_MAIEV_ROAR, Seconds(3));
+ break;
+ case EVENT_MAIEV_ROAR:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR);
+ _events.ScheduleEvent(EVENT_MAIEV_COMBAT, Seconds(3));
+ break;
+ case EVENT_MAIEV_COMBAT:
+ me->SetReactState(REACT_AGGRESSIVE);
+ if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
+ AttackStart(illidan);
+ break;
+ case EVENT_CAGE_TRAP:
+ if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
+ illidan->CastSpell(illidan, SPELL_CAGED_TRAP_TELEPORT, true);
+ DoCastSelf(SPELL_CAGE_TRAP_SUMMON);
+ Talk(SAY_MAIEV_SHADOWSONG_TRAP);
+ _events.Repeat(Seconds(30));
+ break;
+ case EVENT_SHADOW_STRIKE:
+ DoCastVictim(SPELL_SHADOW_STRIKE);
+ _events.Repeat(Seconds(50));
+ break;
+ case EVENT_THROW_DAGGER:
+ if (Unit* target = me->GetVictim())
+ if (!me->IsWithinMeleeRange(target))
+ {
+ DoCastVictim(SPELL_THROW_DAGGER);
+ _events.Repeat(Seconds(5));
+ break;
+ }
+ _events.Repeat(Seconds(1));
+ break;
+ case EVENT_TAUNT:
+ Talk(SAY_MAIEV_SHADOWSONG_TAUNT);
+ _events.Repeat(Seconds(30), Seconds(60));
+ break;
+ case EVENT_MAIEV_OUTRO_TEXT:
+ Talk(SAY_MAIEV_SHADOWSONG_OUTRO);
+ _events.ScheduleEvent(EVENT_MAIEV_FAREWELL_TEXT, Seconds(11));
+ break;
+ case EVENT_MAIEV_FAREWELL_TEXT:
+ Talk(SAY_MAIEV_SHADOWSONG_FAREWELL);
+ _events.ScheduleEvent(EVENT_MAIEV_TELEPORT_DESPAWN, Seconds(3));
+ break;
+ case EVENT_MAIEV_TELEPORT_DESPAWN:
+ DoCastSelf(SPELL_TELEPORT_VISUAL);
+ me->DespawnOrUnsummon(Seconds(1));
+ break;
+ default:
+ break;
}
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim() && !_events.IsInPhase(PHASE_INTRO))
- return;
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
+ }
- _events.Update(diff);
-
- while (uint32 eventId = _events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_MAIEV_APPEAR:
- Talk(SAY_MAIEV_SHADOWSONG_APPEAR);
- break;
- case EVENT_MAIEV_EXCLAMATION:
- me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION);
- break;
- case EVENT_MAIEV_JUSTICE_TEXT:
- Talk(SAY_MAIEV_SHADOWSONG_JUSTICE);
- _events.ScheduleEvent(EVENT_MAIEV_YES, Seconds(2));
- break;
- case EVENT_MAIEV_YES:
- me->HandleEmoteCommand(EMOTE_ONESHOT_YES);
- _events.ScheduleEvent(EVENT_MAIEV_ROAR, Seconds(3));
- break;
- case EVENT_MAIEV_ROAR:
- me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR);
- _events.ScheduleEvent(EVENT_MAIEV_COMBAT, Seconds(3));
- break;
- case EVENT_MAIEV_COMBAT:
- me->SetReactState(REACT_AGGRESSIVE);
- if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
- AttackStart(illidan);
- break;
- case EVENT_CAGE_TRAP:
- if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
- illidan->CastSpell(illidan, SPELL_CAGED_TRAP_TELEPORT, true);
- DoCastSelf(SPELL_CAGE_TRAP_SUMMON);
- Talk(SAY_MAIEV_SHADOWSONG_TRAP);
- _events.Repeat(Seconds(30));
- break;
- case EVENT_SHADOW_STRIKE:
- DoCastVictim(SPELL_SHADOW_STRIKE);
- _events.Repeat(Seconds(50));
- break;
- case EVENT_THROW_DAGGER:
- if (Unit* target = me->GetVictim())
- if (!me->IsWithinMeleeRange(target))
- {
- DoCastVictim(SPELL_THROW_DAGGER);
- _events.Repeat(Seconds(5));
- break;
- }
- _events.Repeat(Seconds(1));
- break;
- case EVENT_TAUNT:
- Talk(SAY_MAIEV_SHADOWSONG_TAUNT);
- _events.Repeat(Seconds(30), Seconds(60));
- break;
- case EVENT_MAIEV_OUTRO_TEXT:
- Talk(SAY_MAIEV_SHADOWSONG_OUTRO);
- _events.ScheduleEvent(EVENT_MAIEV_FAREWELL_TEXT, Seconds(11));
- break;
- case EVENT_MAIEV_FAREWELL_TEXT:
- Talk(SAY_MAIEV_SHADOWSONG_FAREWELL);
- _events.ScheduleEvent(EVENT_MAIEV_TELEPORT_DESPAWN, Seconds(3));
- break;
- case EVENT_MAIEV_TELEPORT_DESPAWN:
- DoCastSelf(SPELL_TELEPORT_VISUAL);
- me->DespawnOrUnsummon(Seconds(1));
- break;
- default:
- break;
- }
+ DoMeleeAttackIfReady();
+ }
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- }
+private:
+ EventMap _events;
+ InstanceScript* _instance;
+ bool _canDown;
+};
- DoMeleeAttackIfReady();
- }
+struct npc_cage_trap_trigger : public PassiveAI
+{
+ npc_cage_trap_trigger(Creature* creature) : PassiveAI(creature) { }
- private:
- EventMap _events;
- InstanceScript* _instance;
- bool _canDown;
- };
+ void Reset() override
+ {
+ _scheduler.Schedule(Seconds(1), [this](TaskContext checkTarget)
+ {
+ DoCastSelf(SPELL_CAGE_TRAP_PERIODIC);
+ checkTarget.Repeat();
+ });
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void UpdateAI(uint32 diff) override
{
- return GetBlackTempleAI<npc_maievAI>(creature);
+ _scheduler.Update(diff);
}
+
+private:
+ TaskScheduler _scheduler;
};
-class npc_cage_trap_trigger : public CreatureScript
+struct npc_illidari_elite : public ScriptedAI
{
-public:
- npc_cage_trap_trigger() : CreatureScript("npc_cage_trap_trigger") { }
+ npc_illidari_elite(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
- struct npc_cage_trap_triggerAI : public PassiveAI
+ void Reset() override
{
- npc_cage_trap_triggerAI(Creature* creature) : PassiveAI(creature) { }
-
- void Reset() override
+ if (Creature* akama = _instance->GetCreature(DATA_AKAMA))
{
- _scheduler.Schedule(Seconds(1), [this](TaskContext checkTarget)
- {
- DoCastSelf(SPELL_CAGE_TRAP_PERIODIC);
- checkTarget.Repeat();
- });
+ AttackStart(akama);
+ AddThreat(akama, 1000.0f);
}
+ }
- void UpdateAI(uint32 diff) override
- {
- _scheduler.Update(diff);
- }
-
- private:
- TaskScheduler _scheduler;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
+ bool CanAIAttack(Unit const* who) const override
{
- return GetBlackTempleAI<npc_cage_trap_triggerAI>(creature);
+ if (who->GetEntry() == NPC_AKAMA)
+ return true;
+ return false;
}
+
+private:
+ InstanceScript* _instance;
};
// 41077 - Akama Teleport
-class spell_illidan_akama_teleport : public SpellScriptLoader
+class spell_illidan_akama_teleport : public SpellScript
{
- public:
- spell_illidan_akama_teleport() : SpellScriptLoader("spell_illidan_akama_teleport") { }
-
- class spell_illidan_akama_teleport_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_illidan_akama_teleport_SpellScript);
-
- void SetDest(SpellDestination& dest)
- {
- if (Creature* caster = GetCaster()->ToCreature())
- {
- uint32 destination = caster->AI()->GetData(DATA_AKAMA_TELEPORT_POSITION);
- dest.Relocate(AkamaTeleportPositions[destination]);
- }
- }
-
- void Register() override
- {
- OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_illidan_akama_teleport_SpellScript::SetDest, EFFECT_0, TARGET_DEST_NEARBY_ENTRY);
- }
- };
+ PrepareSpellScript(spell_illidan_akama_teleport);
- SpellScript* GetSpellScript() const override
+ void SetDest(SpellDestination& dest)
+ {
+ if (Creature* caster = GetCaster()->ToCreature())
{
- return new spell_illidan_akama_teleport_SpellScript();
+ uint32 destination = caster->AI()->GetData(DATA_AKAMA_TELEPORT_POSITION);
+ dest.Relocate(AkamaTeleportPositions[destination]);
}
+ }
+
+ void Register() override
+ {
+ OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_illidan_akama_teleport::SetDest, EFFECT_0, TARGET_DEST_NEARBY_ENTRY);
+ }
};
// 41268 - Quest - Black Temple - Akama - Door Open
-class spell_illidan_akama_door_channel : public SpellScriptLoader
+class spell_illidan_akama_door_channel : public AuraScript
{
- public:
- spell_illidan_akama_door_channel() : SpellScriptLoader("spell_illidan_akama_door_channel") { }
-
- class spell_illidan_akama_door_channel_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_illidan_akama_door_channel_AuraScript);
+ PrepareAuraScript(spell_illidan_akama_door_channel);
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo({ SPELL_ARCANE_EXPLOSION });
- }
-
- void OnRemoveDummy(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- Unit* target = GetTarget();
- target->CastSpell(target, SPELL_ARCANE_EXPLOSION, true);
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_ARCANE_EXPLOSION });
+ }
- if (InstanceScript* instance = target->GetInstanceScript())
- if (Creature* akama = instance->GetCreature(DATA_AKAMA))
- akama->AI()->DoAction(ACTION_OPEN_DOOR);
- }
+ void OnRemoveDummy(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* target = GetTarget();
+ target->CastSpell(target, SPELL_ARCANE_EXPLOSION, true);
- void Register() override
- {
- AfterEffectRemove += AuraEffectRemoveFn(spell_illidan_akama_door_channel_AuraScript::OnRemoveDummy, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
- }
- };
+ if (InstanceScript* instance = target->GetInstanceScript())
+ if (Creature* akama = instance->GetCreature(DATA_AKAMA))
+ akama->AI()->DoAction(ACTION_OPEN_DOOR);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_illidan_akama_door_channel_AuraScript();
- }
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_illidan_akama_door_channel::OnRemoveDummy, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
};
// 40904 - Draw Soul
-class spell_illidan_draw_soul : public SpellScriptLoader
+class spell_illidan_draw_soul : public SpellScript
{
- public:
- spell_illidan_draw_soul() : SpellScriptLoader("spell_illidan_draw_soul") { }
+ PrepareSpellScript(spell_illidan_draw_soul);
- class spell_illidan_draw_soul_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_illidan_draw_soul_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_DRAW_SOUL_HEAL });
- }
-
- void HandleScriptEffect(SpellEffIndex effIndex)
- {
- PreventHitDefaultEffect(effIndex);
- GetHitUnit()->CastSpell(GetCaster(), SPELL_DRAW_SOUL_HEAL, true);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_DRAW_SOUL_HEAL });
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_illidan_draw_soul_SpellScript::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ void HandleScriptEffect(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ GetHitUnit()->CastSpell(GetCaster(), SPELL_DRAW_SOUL_HEAL, true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_illidan_draw_soul_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_illidan_draw_soul::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
/* 41917 - Parasitic Shadowfiend
41914 - Parasitic Shadowfiend */
-class spell_illidan_parasitic_shadowfiend : public SpellScriptLoader
+class spell_illidan_parasitic_shadowfiend : public AuraScript
{
- public:
- spell_illidan_parasitic_shadowfiend() : SpellScriptLoader("spell_illidan_parasitic_shadowfiend") { }
+ PrepareAuraScript(spell_illidan_parasitic_shadowfiend);
- class spell_illidan_parasitic_shadowfiend_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_illidan_parasitic_shadowfiend_AuraScript);
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SUMMON_PARASITIC_SHADOWFIENDS });
+ }
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_SUMMON_PARASITIC_SHADOWFIENDS });
- }
+ void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ AuraRemoveMode removeMode = GetTargetApplication()->GetRemoveMode();
+ if (removeMode != AURA_REMOVE_BY_EXPIRE && removeMode != AURA_REMOVE_BY_DEATH)
+ return;
- void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- Unit* target = GetTarget();
- target->CastSpell(target, SPELL_SUMMON_PARASITIC_SHADOWFIENDS, true);
- }
+ Unit* target = GetTarget();
+ target->CastSpell(target, SPELL_SUMMON_PARASITIC_SHADOWFIENDS, true);
+ }
- void Register() override
- {
- AfterEffectRemove += AuraEffectRemoveFn(spell_illidan_parasitic_shadowfiend_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
- }
- };
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_illidan_parasitic_shadowfiend::HandleEffectRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
+ }
+};
- AuraScript* GetAuraScript() const override
- {
- return new spell_illidan_parasitic_shadowfiend_AuraScript();
- }
+// 41923 - Remove Parasitic Shadowfiends (SERVERSIDE)
+class spell_illidan_remove_parasitic_shadowfiend : public AuraScript
+{
+ PrepareAuraScript(spell_illidan_remove_parasitic_shadowfiend);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_PARASITIC_SHADOWFIEND, SPELL_PARASITIC_SHADOWFIEND_2 });
+ }
+
+ void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->RemoveAurasDueToSpell(SPELL_PARASITIC_SHADOWFIEND);
+ GetTarget()->RemoveAurasDueToSpell(SPELL_PARASITIC_SHADOWFIEND_2);
+ }
+
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_illidan_remove_parasitic_shadowfiend::HandleApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
};
/* 39635 - Throw Glaive
39849 - Throw Glaive */
-class spell_illidan_throw_warglaive : public SpellScriptLoader
+class spell_illidan_throw_warglaive : public SpellScript
{
- public:
- spell_illidan_throw_warglaive() : SpellScriptLoader("spell_illidan_throw_warglaive") { }
+ PrepareSpellScript(spell_illidan_throw_warglaive);
- class spell_illidan_throw_warglaive_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_illidan_throw_warglaive_SpellScript);
-
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- Unit* target = GetHitUnit();
- target->m_Events.AddEvent(new SummonWarglaiveEvent(target), target->m_Events.CalculateTime(1000));
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_illidan_throw_warglaive_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ Unit* target = GetHitUnit();
+ target->m_Events.AddEvent(new SummonWarglaiveEvent(target), target->m_Events.CalculateTime(1000));
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_illidan_throw_warglaive_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_illidan_throw_warglaive::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
// 39857 - Tear of Azzinoth Summon Channel
-class spell_illidan_tear_of_azzinoth_channel : public SpellScriptLoader
+class spell_illidan_tear_of_azzinoth_channel : public AuraScript
{
- public:
- spell_illidan_tear_of_azzinoth_channel() : SpellScriptLoader("spell_illidan_tear_of_azzinoth_channel") { }
-
- class spell_illidan_tear_of_azzinoth_channel_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_illidan_tear_of_azzinoth_channel_AuraScript);
+ PrepareAuraScript(spell_illidan_tear_of_azzinoth_channel);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_UNCAGED_WRATH });
- }
-
- void OnPeriodic(AuraEffect const* /*aurEff*/)
- {
- PreventDefaultAction();
- if (Unit* caster = GetCaster())
- {
- Unit* target = GetTarget();
- if (caster->GetDistance2d(target) > 25.0f)
- {
- target->CastSpell(target, SPELL_UNCAGED_WRATH, true);
- Remove();
- }
- }
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_UNCAGED_WRATH });
+ }
- void Register() override
+ void OnPeriodic(AuraEffect const* /*aurEff*/)
+ {
+ PreventDefaultAction();
+ if (Unit* caster = GetCaster())
+ {
+ Unit* target = GetTarget();
+ if (caster->GetDistance2d(target) > 25.0f)
{
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidan_tear_of_azzinoth_channel_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ target->CastSpell(target, SPELL_UNCAGED_WRATH, true);
+ Remove();
}
- };
-
- AuraScript* GetAuraScript() const override
- {
- return new spell_illidan_tear_of_azzinoth_channel_AuraScript();
}
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidan_tear_of_azzinoth_channel::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
};
// 40631 - Flame Blast
-class spell_illidan_flame_blast : public SpellScriptLoader
+class spell_illidan_flame_blast : public SpellScript
{
- public:
- spell_illidan_flame_blast() : SpellScriptLoader("spell_illidan_flame_blast") { }
+ PrepareSpellScript(spell_illidan_flame_blast);
- class spell_illidan_flame_blast_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_illidan_flame_blast_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_BLAZE_SUMMON });
- }
-
- void HandleBlaze(SpellEffIndex /*effIndex*/)
- {
- Unit* target = GetHitUnit();
- if (target->GetTypeId() == TYPEID_PLAYER)
- target->CastSpell(target, SPELL_BLAZE_SUMMON, true);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_BLAZE_SUMMON });
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_illidan_flame_blast_SpellScript::HandleBlaze, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
- }
- };
+ void HandleBlaze(SpellEffIndex /*effIndex*/)
+ {
+ Unit* target = GetHitUnit();
+ if (target->GetTypeId() == TYPEID_PLAYER)
+ target->CastSpell(target, SPELL_BLAZE_SUMMON, true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_illidan_flame_blast_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_illidan_flame_blast::HandleBlaze, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
+ }
};
// 39873 - Glaive Returns
-class spell_illidan_return_glaives : public SpellScriptLoader
+class spell_illidan_return_glaives : public SpellScript
{
- public: spell_illidan_return_glaives() : SpellScriptLoader("spell_illidan_return_glaives") { }
-
- class spell_illidan_return_glaives_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_illidan_return_glaives_SpellScript);
-
- void HandleScriptEffect(SpellEffIndex /*effIndex*/)
- {
- GetHitUnit()->SendPlaySpellVisual(SPELL_GLAIVE_VISUAL_KIT);
- if (Creature* caster = GetCaster()->ToCreature())
- caster->DespawnOrUnsummon();
- }
+ PrepareSpellScript(spell_illidan_return_glaives);
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_illidan_return_glaives_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ void HandleScriptEffect(SpellEffIndex /*effIndex*/)
+ {
+ GetHitUnit()->SendPlaySpellVisual(SPELL_GLAIVE_VISUAL_KIT);
+ if (Creature* caster = GetCaster()->ToCreature())
+ caster->DespawnOrUnsummon();
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_illidan_return_glaives_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_illidan_return_glaives::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
// 40834 - Agonizing Flames
-class spell_illidan_agonizing_flames : public SpellScriptLoader
+class spell_illidan_agonizing_flames : public SpellScript
{
- public:
- spell_illidan_agonizing_flames() : SpellScriptLoader("spell_illidan_agonizing_flames") { }
-
- class spell_illidan_agonizing_flames_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_illidan_agonizing_flames_SpellScript);
+ PrepareSpellScript(spell_illidan_agonizing_flames);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_AGONIZING_FLAMES });
- }
-
- void FilterTargets(std::list<WorldObject*>& targets)
- {
- if (targets.empty())
- return;
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_AGONIZING_FLAMES });
+ }
- WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
- targets.clear();
- targets.push_back(target);
- }
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ if (targets.empty())
+ return;
- void HandleScript(SpellEffIndex /*effIndex*/)
- {
- GetCaster()->CastSpell(GetHitUnit(), SPELL_AGONIZING_FLAMES, true);
- }
+ WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
+ targets.clear();
+ targets.push_back(target);
+ }
- void Register() override
- {
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_illidan_agonizing_flames_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
- OnEffectHitTarget += SpellEffectFn(spell_illidan_agonizing_flames_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->CastSpell(GetHitUnit(), SPELL_AGONIZING_FLAMES, true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_illidan_agonizing_flames_SpellScript();
- }
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_illidan_agonizing_flames::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnEffectHitTarget += SpellEffectFn(spell_illidan_agonizing_flames::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
// 40511 - Demon Transform 1
-class spell_illidan_demon_transform1 : public SpellScriptLoader
+class spell_illidan_demon_transform1 : public AuraScript
{
- public:
- spell_illidan_demon_transform1() : SpellScriptLoader("spell_illidan_demon_transform1") { }
-
- class spell_illidan_demon_transform1_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_illidan_demon_transform1_AuraScript);
+ PrepareAuraScript(spell_illidan_demon_transform1);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_DEMON_TRANSFORM_2 });
- }
-
- void OnPeriodic(AuraEffect const* /*aurEff*/)
- {
- PreventDefaultAction();
- GetTarget()->CastSpell(GetTarget(), SPELL_DEMON_TRANSFORM_2, true);
- Remove();
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_DEMON_TRANSFORM_2 });
+ }
- void Register() override
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidan_demon_transform1_AuraScript::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
- }
- };
+ void OnPeriodic(AuraEffect const* /*aurEff*/)
+ {
+ PreventDefaultAction();
+ GetTarget()->CastSpell(GetTarget(), SPELL_DEMON_TRANSFORM_2, true);
+ Remove();
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_illidan_demon_transform1_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidan_demon_transform1::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
};
+
// 40398 - Demon Transform 2
-class spell_illidan_demon_transform2 : public SpellScriptLoader
+class spell_illidan_demon_transform2 : public AuraScript
{
- public:
- spell_illidan_demon_transform2() : SpellScriptLoader("spell_illidan_demon_transform2") { }
-
- class spell_illidan_demon_transform2_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_illidan_demon_transform2_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_DEMON_FORM, SPELL_DEMON_TRANSFORM_3 });
- }
-
- void OnPeriodic(AuraEffect const* aurEff)
- {
- PreventDefaultAction();
- Unit* target = GetTarget();
+ PrepareAuraScript(spell_illidan_demon_transform2);
- if (aurEff->GetTickNumber() == 1)
- {
- if (target->GetDisplayId() == target->GetNativeDisplayId())
- target->CastSpell(target, SPELL_DEMON_FORM, true);
- else
- target->RemoveAurasDueToSpell(SPELL_DEMON_FORM);
- }
- else if (aurEff->GetTickNumber() == 2)
- {
- target->CastSpell(target, SPELL_DEMON_TRANSFORM_3, true);
- if (Aura* aura = GetUnitOwner()->GetAura(SPELL_DEMON_TRANSFORM_3))
- aura->SetDuration(4300);
- Remove();
- }
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_DEMON_FORM, SPELL_DEMON_TRANSFORM_3 });
+ }
- void Register() override
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidan_demon_transform2_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
- }
- };
+ void OnPeriodic(AuraEffect const* aurEff)
+ {
+ PreventDefaultAction();
+ Unit* target = GetTarget();
- AuraScript* GetAuraScript() const override
+ if (aurEff->GetTickNumber() == 1)
+ {
+ if (target->GetDisplayId() == target->GetNativeDisplayId())
+ target->CastSpell(target, SPELL_DEMON_FORM, true);
+ else
+ target->RemoveAurasDueToSpell(SPELL_DEMON_FORM);
+ }
+ else if (aurEff->GetTickNumber() == 2)
{
- return new spell_illidan_demon_transform2_AuraScript();
+ target->CastSpell(target, SPELL_DEMON_TRANSFORM_3, true);
+ if (Aura* aura = GetUnitOwner()->GetAura(SPELL_DEMON_TRANSFORM_3))
+ aura->SetDuration(4300);
+ Remove();
}
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidan_demon_transform2::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
};
// 41126 - Flame Burst
-class spell_illidan_flame_burst : public SpellScriptLoader
+class spell_illidan_flame_burst : public SpellScript
{
- public:
- spell_illidan_flame_burst() : SpellScriptLoader("spell_illidan_flame_burst") { }
-
- class spell_illidan_flame_burst_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_illidan_flame_burst_SpellScript);
+ PrepareSpellScript(spell_illidan_flame_burst);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_FLAME_BURST_EFFECT });
- }
-
- void HandleScriptEffect(SpellEffIndex /*effIndex*/)
- {
- GetHitUnit()->CastSpell(GetHitUnit(), SPELL_FLAME_BURST_EFFECT, true);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_FLAME_BURST_EFFECT });
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_illidan_flame_burst_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ void HandleScriptEffect(SpellEffIndex /*effIndex*/)
+ {
+ GetHitUnit()->CastSpell(GetHitUnit(), SPELL_FLAME_BURST_EFFECT, true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_illidan_flame_burst_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_illidan_flame_burst::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
// 41081 - Find Target
-class spell_illidan_find_target : public SpellScriptLoader
+class spell_illidan_find_target : public SpellScript
{
- public:
- spell_illidan_find_target() : SpellScriptLoader("spell_illidan_find_target") { }
-
- class spell_illidan_find_target_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_illidan_find_target_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_PARALYZE });
- }
+ PrepareSpellScript(spell_illidan_find_target);
- void FilterTargets(std::list<WorldObject*>& targets)
- {
- targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_PARALYZE));
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_PARALYZE });
+ }
- if (targets.empty())
- return;
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_PARALYZE));
- WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
- targets.clear();
- targets.push_back(target);
- }
+ if (targets.empty())
+ return;
- void HandleScript(SpellEffIndex /*effIndex*/)
- {
- Unit* target = GetHitUnit();
- if (Creature* caster = GetCaster()->ToCreature())
- {
- caster->CastSpell(target, SPELL_PARALYZE, true);
- caster->AI()->SetGUID(target->GetGUID(), 0);
- }
- }
-
- void Register() override
- {
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_illidan_find_target_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
- OnEffectHitTarget += SpellEffectFn(spell_illidan_find_target_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
+ targets.clear();
+ targets.push_back(target);
+ }
- SpellScript* GetSpellScript() const override
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Unit* target = GetHitUnit();
+ if (Creature* caster = GetCaster()->ToCreature())
{
- return new spell_illidan_find_target_SpellScript();
+ caster->CastSpell(target, SPELL_PARALYZE, true);
+ caster->AI()->SetGUID(target->GetGUID(), 0);
}
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_illidan_find_target::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnEffectHitTarget += SpellEffectFn(spell_illidan_find_target::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
// 39908 - Eye Blast
-class spell_illidan_eye_blast : public SpellScriptLoader
+class spell_illidan_eye_blast : public AuraScript
{
- public:
- spell_illidan_eye_blast() : SpellScriptLoader("spell_illidan_eye_blast") { }
-
- class spell_illidan_eye_blast_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_illidan_eye_blast_AuraScript);
-
- void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- if (Creature* target = GetTarget()->ToCreature())
- target->DespawnOrUnsummon();
- }
+ PrepareAuraScript(spell_illidan_eye_blast);
- void Register() override
- {
- AfterEffectRemove += AuraEffectRemoveFn(spell_illidan_eye_blast_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
- }
- };
+ void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Creature* target = GetTarget()->ToCreature())
+ target->DespawnOrUnsummon();
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_illidan_eye_blast_AuraScript();
- }
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_illidan_eye_blast::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
};
// 40761 - Cage Trap
-class spell_illidan_cage_trap : public SpellScriptLoader
+class spell_illidan_cage_trap : public SpellScript
{
- public:
- spell_illidan_cage_trap() : SpellScriptLoader("spell_illidan_cage_trap") { }
-
- class spell_illidan_cage_trap_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_illidan_cage_trap_SpellScript);
-
- void HandleScriptEffect(SpellEffIndex /*effIndex*/)
- {
- Creature* target = GetHitCreature();
- Creature* caster = GetCaster()->ToCreature();
-
- if (!target || !caster)
- return;
+ PrepareSpellScript(spell_illidan_cage_trap);
- if (caster->GetDistance2d(target) < 4.0f)
- {
- target->AI()->DoAction(ACTION_ILLIDAN_CAGED);
- caster->DespawnOrUnsummon();
- if (GameObject* trap = target->FindNearestGameObject(GO_ILLIDAN_CAGE_TRAP, 10.0f))
- trap->UseDoorOrButton();
- }
- }
+ void HandleScriptEffect(SpellEffIndex /*effIndex*/)
+ {
+ Creature* target = GetHitCreature();
+ Creature* caster = GetCaster()->ToCreature();
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_illidan_cage_trap_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ if (!target || !caster)
+ return;
- SpellScript* GetSpellScript() const override
+ if (caster->GetDistance2d(target) < 4.0f)
{
- return new spell_illidan_cage_trap_SpellScript();
+ target->AI()->DoAction(ACTION_ILLIDAN_CAGED);
+ caster->DespawnOrUnsummon();
+ if (GameObject* trap = target->FindNearestGameObject(GO_ILLIDAN_CAGE_TRAP, 10.0f))
+ trap->UseDoorOrButton();
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_illidan_cage_trap::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
// 40760 - Cage Trap
-class spell_illidan_caged : public SpellScriptLoader
+class spell_illidan_caged : public AuraScript
{
- public:
- spell_illidan_caged() : SpellScriptLoader("spell_illidan_caged") { }
-
- class spell_illidan_caged_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_illidan_caged_AuraScript);
+ PrepareAuraScript(spell_illidan_caged);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_CAGED_DEBUFF });
- }
-
- void OnPeriodic(AuraEffect const* /*aurEff*/)
- {
- PreventDefaultAction();
- Unit* target = GetTarget();
- target->CastSpell(target, SPELL_CAGED_DEBUFF, true);
- Remove();
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_CAGED_DEBUFF });
+ }
- void Register() override
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidan_caged_AuraScript::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
- }
- };
+ void OnPeriodic(AuraEffect const* /*aurEff*/)
+ {
+ PreventDefaultAction();
+ Unit* target = GetTarget();
+ target->CastSpell(target, SPELL_CAGED_DEBUFF, true);
+ Remove();
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_illidan_caged_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidan_caged::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
};
// 40409 - Maiev Down
-class spell_maiev_down : public SpellScriptLoader
+class spell_maiev_down : public AuraScript
{
-public:
- spell_maiev_down() : SpellScriptLoader("spell_maiev_down") { }
+ PrepareAuraScript(spell_maiev_down);
- class spell_maiev_down_AuraScript : public AuraScript
+ bool Load() override
{
- PrepareAuraScript(spell_maiev_down_AuraScript);
-
- bool Load() override
- {
- return GetUnitOwner()->GetTypeId() == TYPEID_UNIT;
- }
-
- void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- GetTarget()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- }
+ return GetUnitOwner()->GetTypeId() == TYPEID_UNIT;
+ }
- void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- GetTarget()->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- GetTarget()->GetAI()->DoAction(ACTION_MAIEV_DOWN_FADE);
- }
+ void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ }
- void Register() override
- {
- OnEffectApply += AuraEffectApplyFn(spell_maiev_down_AuraScript::HandleEffectApply, EFFECT_1, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
- AfterEffectRemove += AuraEffectRemoveFn(spell_maiev_down_AuraScript::HandleEffectRemove, EFFECT_1, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
- }
- };
+ void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ GetTarget()->GetAI()->DoAction(ACTION_MAIEV_DOWN_FADE);
+ }
- AuraScript* GetAuraScript() const override
+ void Register() override
{
- return new spell_maiev_down_AuraScript();
+ OnEffectApply += AuraEffectApplyFn(spell_maiev_down::HandleEffectApply, EFFECT_1, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_maiev_down::HandleEffectRemove, EFFECT_1, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
}
};
// 40693 - Cage Trap
-class spell_illidan_cage_teleport : public SpellScriptLoader
+class spell_illidan_cage_teleport : public SpellScript
{
- public:
- spell_illidan_cage_teleport() : SpellScriptLoader("spell_illidan_cage_teleport") { }
-
- class spell_illidan_cage_teleport_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_illidan_cage_teleport_SpellScript);
-
- void SetDest(SpellDestination& dest)
- {
- Position offset = { 0.0f, 0.0f, GetCaster()->GetPositionZ(), 0.0f };
- dest.RelocateOffset(offset);
- }
+ PrepareSpellScript(spell_illidan_cage_teleport);
- void Register() override
- {
- OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_illidan_cage_teleport_SpellScript::SetDest, EFFECT_0, TARGET_DEST_CASTER_RADIUS);
- }
- };
+ void SetDest(SpellDestination& dest)
+ {
+ Position offset = { 0.0f, 0.0f, GetCaster()->GetPositionZ(), 0.0f };
+ dest.RelocateOffset(offset);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_illidan_cage_teleport_SpellScript();
- }
+ void Register() override
+ {
+ OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_illidan_cage_teleport::SetDest, EFFECT_0, TARGET_DEST_CASTER_RADIUS);
+ }
};
// 41242 - Akama Despawn
-class spell_illidan_despawn_akama : public SpellScriptLoader
+class spell_illidan_despawn_akama : public SpellScript
{
- public:
- spell_illidan_despawn_akama() : SpellScriptLoader("spell_illidan_despawn_akama") { }
-
- class spell_illidan_despawn_akama_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_illidan_despawn_akama_SpellScript);
+ PrepareSpellScript(spell_illidan_despawn_akama);
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- if (Creature* target = GetHitCreature())
- target->DespawnOrUnsummon(Seconds(1));
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_illidan_despawn_akama_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ if (Creature* target = GetHitCreature())
+ target->DespawnOrUnsummon(Seconds(1));
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_illidan_despawn_akama_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_illidan_despawn_akama::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
void AddSC_boss_illidan()
{
- new boss_illidan_stormrage();
- new npc_akama();
- new npc_parasitic_shadowfiend();
- new npc_blade_of_azzinoth();
- new npc_flame_of_azzinoth();
- new npc_illidan_db_target();
- new npc_maiev();
- new npc_illidan_shadow_demon();
- new npc_cage_trap_trigger();
- new spell_illidan_akama_teleport();
- new spell_illidan_akama_door_channel();
- new spell_illidan_draw_soul();
- new spell_illidan_parasitic_shadowfiend();
- new spell_illidan_throw_warglaive();
- new spell_illidan_tear_of_azzinoth_channel();
- new spell_illidan_flame_blast();
- new spell_illidan_return_glaives();
- new spell_illidan_agonizing_flames();
- new spell_illidan_demon_transform1();
- new spell_illidan_demon_transform2();
- new spell_illidan_flame_burst();
- new spell_illidan_find_target();
- new spell_illidan_eye_blast();
- new spell_illidan_cage_trap();
- new spell_illidan_caged();
- new spell_maiev_down();
- new spell_illidan_cage_teleport();
- new spell_illidan_despawn_akama();
+ RegisterBlackTempleCreatureAI(boss_illidan_stormrage);
+ RegisterBlackTempleCreatureAI(npc_akama_illidan);
+ RegisterBlackTempleCreatureAI(npc_parasitic_shadowfiend);
+ RegisterBlackTempleCreatureAI(npc_blade_of_azzinoth);
+ RegisterBlackTempleCreatureAI(npc_flame_of_azzinoth);
+ RegisterBlackTempleCreatureAI(npc_illidan_db_target);
+ RegisterBlackTempleCreatureAI(npc_maiev);
+ RegisterBlackTempleCreatureAI(npc_shadow_demon);
+ RegisterBlackTempleCreatureAI(npc_cage_trap_trigger);
+ RegisterBlackTempleCreatureAI(npc_illidari_elite);
+ RegisterSpellScript(spell_illidan_akama_teleport);
+ RegisterAuraScript(spell_illidan_akama_door_channel);
+ RegisterSpellScript(spell_illidan_draw_soul);
+ RegisterAuraScript(spell_illidan_parasitic_shadowfiend);
+ RegisterAuraScript(spell_illidan_remove_parasitic_shadowfiend);
+ RegisterSpellScript(spell_illidan_throw_warglaive);
+ RegisterAuraScript(spell_illidan_tear_of_azzinoth_channel);
+ RegisterSpellScript(spell_illidan_flame_blast);
+ RegisterSpellScript(spell_illidan_return_glaives);
+ RegisterSpellScript(spell_illidan_agonizing_flames);
+ RegisterAuraScript(spell_illidan_demon_transform1);
+ RegisterAuraScript(spell_illidan_demon_transform2);
+ RegisterSpellScript(spell_illidan_flame_burst);
+ RegisterSpellScript(spell_illidan_find_target);
+ RegisterAuraScript(spell_illidan_eye_blast);
+ RegisterSpellScript(spell_illidan_cage_trap);
+ RegisterAuraScript(spell_illidan_caged);
+ RegisterAuraScript(spell_maiev_down);
+ RegisterSpellScript(spell_illidan_cage_teleport);
+ RegisterSpellScript(spell_illidan_despawn_akama);
}
diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidari_council.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidari_council.cpp
index 245f7960628..72597d52d42 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_illidari_council.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_illidari_council.cpp
@@ -27,63 +27,63 @@
enum Says
{
- SAY_COUNCIL_AGRO = 0,
- SAY_COUNCIL_ENRAGE = 1,
- SAY_COUNCIL_SPECIAL = 2,
- SAY_COUNCIL_SLAY = 3,
- SAY_COUNCIL_COMNT = 4,
- SAY_COUNCIL_DEATH = 5
+ SAY_COUNCIL_AGRO = 0,
+ SAY_COUNCIL_ENRAGE = 1,
+ SAY_COUNCIL_SPECIAL = 2,
+ SAY_COUNCIL_SLAY = 3,
+ SAY_COUNCIL_COMNT = 4,
+ SAY_COUNCIL_DEATH = 5
};
enum Spells
{
// Illidari Council (Trigger)
- SPELL_EMPYREAL_BALANCE = 41499,
- SPELL_EMPYREAL_EQUIVALENCY = 41333,
+ SPELL_EMPYREAL_BALANCE = 41499,
+ SPELL_EMPYREAL_EQUIVALENCY = 41333,
// Generic
- SPELL_SHARED_RULE = 41342,
- SPELL_BERSERK = 45078,
- SPELL_BALANCE_OF_POWER = 41341,
- SPELL_QUIET_SUICIDE = 3617, // Serverside spell
+ SPELL_SHARED_RULE = 41342,
+ SPELL_BERSERK = 45078,
+ SPELL_BALANCE_OF_POWER = 41341,
+ SPELL_QUIET_SUICIDE = 3617,
// High Nethermancer Zerevor's
- SPELL_FLAMESTRIKE = 41481,
- SPELL_BLIZZARD = 41482,
- SPELL_ARCANE_BOLT = 41483,
- SPELL_ARCANE_EXPLOSION = 41524,
- SPELL_DAMPEN_MAGIC = 41478,
+ SPELL_FLAMESTRIKE = 41481,
+ SPELL_BLIZZARD = 41482,
+ SPELL_ARCANE_BOLT = 41483,
+ SPELL_ARCANE_EXPLOSION = 41524,
+ SPELL_DAMPEN_MAGIC = 41478,
// Lady Malande's
- SPELL_EMPOWERED_SMITE = 41471,
- SPELL_CIRCLE_OF_HEALING = 41455,
- SPELL_REFLECTIVE_SHIELD = 41475,
- SPELL_REFLECTIVE_SHIELD_DAMAGE = 33619,
- SPELL_DIVINE_WRATH = 41472,
+ SPELL_EMPOWERED_SMITE = 41471,
+ SPELL_CIRCLE_OF_HEALING = 41455,
+ SPELL_REFLECTIVE_SHIELD = 41475,
+ SPELL_REFLECTIVE_SHIELD_DAMAGE = 33619,
+ SPELL_DIVINE_WRATH = 41472,
// Gathios the Shatterer's
- SPELL_BLESS_PROTECTION = 41450,
- SPELL_BLESS_SPELL_WARDING = 41451,
- SPELL_CONSECRATION = 41541,
- SPELL_HAMMER_OF_JUSTICE = 41468,
- SPELL_SEAL_OF_COMMAND = 41469,
- SPELL_SEAL_OF_BLOOD = 41459,
- SPELL_CHROMATIC_AURA = 41453,
- SPELL_DEVOTION_AURA = 41452,
- SPELL_JUDGEMENT_PRIMER = 41473,
- SPELL_JUDGEMENT = 41467,
- SPELL_JUDGEMENT_OF_COMMAND = 41470,
- SPELL_JUDGEMENT_OF_BLOOD = 41461,
+ SPELL_BLESS_PROTECTION = 41450,
+ SPELL_BLESS_SPELL_WARDING = 41451,
+ SPELL_CONSECRATION = 41541,
+ SPELL_HAMMER_OF_JUSTICE = 41468,
+ SPELL_SEAL_OF_COMMAND = 41469,
+ SPELL_SEAL_OF_BLOOD = 41459,
+ SPELL_CHROMATIC_AURA = 41453,
+ SPELL_DEVOTION_AURA = 41452,
+ SPELL_JUDGEMENT_PRIMER = 41473,
+ SPELL_JUDGEMENT = 41467,
+ SPELL_JUDGEMENT_OF_COMMAND = 41470,
+ SPELL_JUDGEMENT_OF_BLOOD = 41461,
// Veras Darkshadow's
- SPELL_DEADLY_STRIKE = 41480,
- SPELL_DEADLY_POISON = 41485,
- SPELL_ENVENOM = 41487,
- SPELL_VANISH = 41476,
+ SPELL_DEADLY_STRIKE = 41480,
+ SPELL_DEADLY_POISON = 41485,
+ SPELL_ENVENOM = 41487,
+ SPELL_VANISH = 41476,
// Veras Vanish Effect
- SPELL_BIRTH = 40031,
- SPELL_ENVENOM_DUMMY = 41510
+ SPELL_BIRTH = 40031,
+ SPELL_ENVENOM_DUMMY = 41510
};
enum IllidariEvents
@@ -131,123 +131,113 @@ static uint32 GetRandomBossExcept(uint32 exception)
return bossData[urand(0, 3)];
}
-class boss_illidari_council : public CreatureScript
+struct boss_illidari_council : public BossAI
{
-public:
- boss_illidari_council() : CreatureScript("boss_illidari_council") { }
+ boss_illidari_council(Creature* creature) : BossAI(creature, DATA_ILLIDARI_COUNCIL), _inCombat(false) { }
- struct boss_illidari_councilAI : public BossAI
+ void Reset() override
{
- boss_illidari_councilAI(Creature* creature) : BossAI(creature, DATA_ILLIDARI_COUNCIL), _inCombat(false) { }
-
- void Reset() override
- {
- _Reset();
- _inCombat = false;
- me->SummonCreatureGroup(SUMMON_COUNCIL_GROUP);
- DoCastSelf(SPELL_EMPYREAL_BALANCE, true);
- }
+ _Reset();
+ _inCombat = false;
+ me->SummonCreatureGroup(SUMMON_COUNCIL_GROUP);
+ DoCastSelf(SPELL_EMPYREAL_BALANCE, true);
+ }
- void EnterCombat(Unit* /*who*/) override
+ void EnterCombat(Unit* /*who*/) override
+ {
+ if (!_inCombat)
{
- if (!_inCombat)
+ _inCombat = true;
+ _EnterCombat();
+ for (uint32 bossData : CouncilData)
{
- _inCombat = true;
- _EnterCombat();
- for (uint32 bossData : CouncilData)
+ if (Creature* council = instance->GetCreature(bossData))
{
- if (Creature* council = instance->GetCreature(bossData))
- {
- instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, council);
- DoZoneInCombat(council);
- }
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, council);
+ DoZoneInCombat(council);
}
- events.ScheduleEvent(EVENT_EMPYREAL_EQUIVALENCY, Seconds(2));
- events.ScheduleEvent(EVENT_BERSERK, Minutes(15));
- if (Creature* council = instance->GetCreature(CouncilData[urand(0, 3)]))
- council->AI()->Talk(SAY_COUNCIL_AGRO);
}
+ events.ScheduleEvent(EVENT_EMPYREAL_EQUIVALENCY, Seconds(2));
+ events.ScheduleEvent(EVENT_BERSERK, Minutes(15));
+ if (Creature* council = instance->GetCreature(CouncilData[urand(0, 3)]))
+ council->AI()->Talk(SAY_COUNCIL_AGRO);
}
+ }
- void EnterEvadeMode(EvadeReason /*why*/) override
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ if (!me->IsInEvadeMode())
{
- if (!me->IsInEvadeMode())
- {
- _inCombat = false;
- for (uint32 bossData : CouncilData)
- if (Creature* council = instance->GetCreature(bossData))
- instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, council);
+ _inCombat = false;
+ for (uint32 bossData : CouncilData)
+ if (Creature* council = instance->GetCreature(bossData))
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, council);
- summons.DespawnAll();
- _DespawnAtEvade();
- }
+ summons.DespawnAll();
+ _DespawnAtEvade();
}
+ }
- void JustDied(Unit* /*killer*/) override
- {
- _inCombat = false;
- events.Reset();
- instance->SetBossState(DATA_ILLIDARI_COUNCIL, DONE);
+ void JustDied(Unit* /*killer*/) override
+ {
+ _inCombat = false;
+ events.Reset();
+ instance->SetBossState(DATA_ILLIDARI_COUNCIL, DONE);
- for (uint32 bossData : CouncilData)
+ for (uint32 bossData : CouncilData)
+ {
+ if (Creature* council = instance->GetCreature(bossData))
{
- if (Creature* council = instance->GetCreature(bossData))
- {
- // Allow loot
- instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, council);
- council->LowerPlayerDamageReq(council->GetMaxHealth());
- council->CastSpell(council, SPELL_QUIET_SUICIDE, true);
- }
+ // Allow loot
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, council);
+ council->LowerPlayerDamageReq(council->GetMaxHealth());
+ council->CastSpell(council, SPELL_QUIET_SUICIDE, true);
}
}
+ }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- events.Update(diff);
+ events.Update(diff);
- while (uint32 eventId = events.ExecuteEvent())
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- switch (eventId)
- {
- case EVENT_EMPYREAL_EQUIVALENCY:
- DoCastSelf(SPELL_EMPYREAL_EQUIVALENCY, true);
- events.Repeat(Seconds(2));
- break;
- case EVENT_BERSERK:
- for (uint32 bossData : CouncilData)
+ case EVENT_EMPYREAL_EQUIVALENCY:
+ DoCastSelf(SPELL_EMPYREAL_EQUIVALENCY, true);
+ events.Repeat(Seconds(2));
+ break;
+ case EVENT_BERSERK:
+ for (uint32 bossData : CouncilData)
+ {
+ if (Creature* council = instance->GetCreature(bossData))
{
- if (Creature* council = instance->GetCreature(bossData))
- {
- council->CastSpell(council, SPELL_BERSERK, true);
- council->AI()->Talk(SAY_COUNCIL_ENRAGE);
- }
+ council->CastSpell(council, SPELL_BERSERK, true);
+ council->AI()->Talk(SAY_COUNCIL_ENRAGE);
}
- break;
- default:
- break;
- }
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ }
+ break;
+ default:
+ break;
}
- }
- private:
- bool _inCombat;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<boss_illidari_councilAI>(creature);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
}
+
+private:
+ bool _inCombat;
};
+
struct IllidariCouncilBossAI : public BossAI
{
IllidariCouncilBossAI(Creature* creature, uint32 bossId) : BossAI(creature, bossId), _bossId(bossId)
@@ -317,648 +307,492 @@ private:
Unit const* _me;
};
-class boss_gathios_the_shatterer : public CreatureScript
+struct boss_gathios_the_shatterer : public IllidariCouncilBossAI
{
-public:
- boss_gathios_the_shatterer() : CreatureScript("boss_gathios_the_shatterer") { }
+ boss_gathios_the_shatterer(Creature* creature) : IllidariCouncilBossAI(creature, DATA_GATHIOS_THE_SHATTERER) { }
- struct boss_gathios_the_shattererAI : public IllidariCouncilBossAI
+ void ScheduleEvents() override
{
- boss_gathios_the_shattererAI(Creature* creature) : IllidariCouncilBossAI(creature, DATA_GATHIOS_THE_SHATTERER) { }
-
- void ScheduleEvents() override
- {
- DoCastSelf(SPELL_SEAL_OF_BLOOD);
- events.ScheduleEvent(EVENT_BLESS, Seconds(20));
- events.ScheduleEvent(EVENT_CONSECRATION, Seconds(10));
- events.ScheduleEvent(EVENT_HAMMER_OF_JUSTICE, Seconds(10));
- events.ScheduleEvent(EVENT_JUDGEMENT, Seconds(15));
- events.ScheduleEvent(EVENT_AURA, Seconds(6));
- }
+ DoCastSelf(SPELL_SEAL_OF_BLOOD);
+ events.ScheduleEvent(EVENT_BLESS, Seconds(20));
+ events.ScheduleEvent(EVENT_CONSECRATION, Seconds(10));
+ events.ScheduleEvent(EVENT_HAMMER_OF_JUSTICE, Seconds(10));
+ events.ScheduleEvent(EVENT_JUDGEMENT, Seconds(15));
+ events.ScheduleEvent(EVENT_AURA, Seconds(6));
+ }
- void ExecuteEvent(uint32 eventId) override
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
{
- switch (eventId)
+ case EVENT_BLESS:
{
- case EVENT_BLESS:
- {
- std::list<Unit*> TargetList;
- Trinity::AnyFriendlyUnitInObjectRangeCheck checker(me, me, 100.0f);
- Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(me, TargetList, checker);
- Cell::VisitAllObjects(me, searcher, 100.0f);
+ std::list<Unit*> TargetList;
+ Trinity::AnyFriendlyUnitInObjectRangeCheck checker(me, me, 100.0f);
+ Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(me, TargetList, checker);
+ Cell::VisitAllObjects(me, searcher, 100.0f);
- if (!TargetList.empty())
- {
- Unit* target = Trinity::Containers::SelectRandomContainerElement(TargetList);
- DoCast(target, RAND(SPELL_BLESS_PROTECTION, SPELL_BLESS_SPELL_WARDING));
- }
- events.Repeat(Seconds(30), Seconds(45));
- break;
+ if (!TargetList.empty())
+ {
+ Unit* target = Trinity::Containers::SelectRandomContainerElement(TargetList);
+ DoCast(target, RAND(SPELL_BLESS_PROTECTION, SPELL_BLESS_SPELL_WARDING));
}
- case EVENT_AURA:
- DoCastSelf(RAND(SPELL_CHROMATIC_AURA, SPELL_DEVOTION_AURA));
- events.Repeat(Seconds(30));
- break;
- case EVENT_HAMMER_OF_JUSTICE:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, HammerTargetSelector(me)))
- DoCast(target, SPELL_HAMMER_OF_JUSTICE);
- events.Repeat(Seconds(20));
- break;
- case EVENT_JUDGEMENT:
- DoCastVictim(SPELL_JUDGEMENT);
- events.Repeat(Seconds(15));
- break;
- case EVENT_CONSECRATION:
- DoCastSelf(SPELL_CONSECRATION);
- events.Repeat(Seconds(30), Seconds(35));
- break;
- default:
- break;
- }
+ events.Repeat(Seconds(30), Seconds(45));
+ break;
+ }
+ case EVENT_AURA:
+ DoCastSelf(RAND(SPELL_CHROMATIC_AURA, SPELL_DEVOTION_AURA));
+ events.Repeat(Seconds(30));
+ break;
+ case EVENT_HAMMER_OF_JUSTICE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, HammerTargetSelector(me)))
+ DoCast(target, SPELL_HAMMER_OF_JUSTICE);
+ events.Repeat(Seconds(20));
+ break;
+ case EVENT_JUDGEMENT:
+ DoCastVictim(SPELL_JUDGEMENT);
+ events.Repeat(Seconds(15));
+ break;
+ case EVENT_CONSECRATION:
+ DoCastSelf(SPELL_CONSECRATION);
+ events.Repeat(Seconds(30), Seconds(35));
+ break;
+ default:
+ break;
}
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<boss_gathios_the_shattererAI>(creature);
}
};
-class boss_high_nethermancer_zerevor : public CreatureScript
+struct boss_high_nethermancer_zerevor : public IllidariCouncilBossAI
{
-public:
- boss_high_nethermancer_zerevor() : CreatureScript("boss_high_nethermancer_zerevor") { }
+ boss_high_nethermancer_zerevor(Creature* creature) : IllidariCouncilBossAI(creature, DATA_HIGH_NETHERMANCER_ZEREVOR), _canUseArcaneExplosion(true) { }
- struct boss_high_nethermancer_zerevorAI : public IllidariCouncilBossAI
+ void Reset() override
{
- boss_high_nethermancer_zerevorAI(Creature* creature) : IllidariCouncilBossAI(creature, DATA_HIGH_NETHERMANCER_ZEREVOR), _canUseArcaneExplosion(true) { }
+ IllidariCouncilBossAI::Reset();
+ _canUseArcaneExplosion = true;
+ DoCastSelf(SPELL_DAMPEN_MAGIC);
+ }
- void Reset() override
- {
- IllidariCouncilBossAI::Reset();
- _canUseArcaneExplosion = true;
- DoCastSelf(SPELL_DAMPEN_MAGIC);
- }
+ void ScheduleEvents() override
+ {
+ events.ScheduleEvent(EVENT_FLAMESTRIKE, Seconds(8));
+ events.ScheduleEvent(EVENT_BLIZZARD, Seconds(25));
+ events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, Seconds(5));
+ DoCastSelf(SPELL_DAMPEN_MAGIC);
+ }
- void ScheduleEvents() override
- {
- events.ScheduleEvent(EVENT_FLAMESTRIKE, Seconds(8));
- events.ScheduleEvent(EVENT_BLIZZARD, Seconds(25));
- events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, Seconds(5));
- DoCastSelf(SPELL_DAMPEN_MAGIC);
+ void DoAction(int32 actionId) override
+ {
+ if (actionId == ACTION_REFRESH_DAMPEN)
+ events.ScheduleEvent(EVENT_DAMPEN_MAGIC, Seconds(50));
+ }
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
+ {
+ case EVENT_FLAMESTRIKE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ DoCast(target, SPELL_FLAMESTRIKE);
+ Talk(SAY_COUNCIL_SPECIAL);
+ events.Repeat(Seconds(40));
+ break;
+ case EVENT_BLIZZARD:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ DoCast(target, SPELL_BLIZZARD);
+ events.Repeat(Seconds(15), Seconds(40));
+ break;
+ case EVENT_ARCANE_EXPLOSION_CHECK:
+ _canUseArcaneExplosion = true;
+ break;
+ case EVENT_ARCANE_EXPLOSION:
+ if (_canUseArcaneExplosion && SelectTarget(SELECT_TARGET_RANDOM, 0, 10.0f))
+ {
+ DoCastSelf(SPELL_ARCANE_EXPLOSION);
+ _canUseArcaneExplosion = false;
+ events.ScheduleEvent(EVENT_ARCANE_EXPLOSION_CHECK, Seconds(5));
+ }
+ events.Repeat(Seconds(1));
+ break;
+ case EVENT_DAMPEN_MAGIC:
+ DoCastSelf(SPELL_DAMPEN_MAGIC);
+ break;
+ default:
+ break;
}
+ }
- void DoAction(int32 actionId) override
- {
- if (actionId == ACTION_REFRESH_DAMPEN)
- events.ScheduleEvent(EVENT_DAMPEN_MAGIC, Seconds(50));
- }
- void ExecuteEvent(uint32 eventId) override
- {
- switch (eventId)
- {
- case EVENT_FLAMESTRIKE:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, SPELL_FLAMESTRIKE);
- Talk(SAY_COUNCIL_SPECIAL);
- events.Repeat(Seconds(40));
- break;
- case EVENT_BLIZZARD:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, SPELL_BLIZZARD);
- events.Repeat(Seconds(15), Seconds(40));
- break;
- case EVENT_ARCANE_EXPLOSION_CHECK:
- _canUseArcaneExplosion = true;
- break;
- case EVENT_ARCANE_EXPLOSION:
- if (_canUseArcaneExplosion && SelectTarget(SELECT_TARGET_RANDOM, 0, 10.0f))
- {
- DoCastSelf(SPELL_ARCANE_EXPLOSION);
- _canUseArcaneExplosion = false;
- events.ScheduleEvent(EVENT_ARCANE_EXPLOSION_CHECK, Seconds(5));
- }
- events.Repeat(Seconds(1));
- break;
- case EVENT_DAMPEN_MAGIC:
- DoCastSelf(SPELL_DAMPEN_MAGIC);
- break;
- default:
- break;
- }
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ events.Update(diff);
- events.Update(diff);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ ExecuteEvent(eventId);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
-
- while (uint32 eventId = events.ExecuteEvent())
- {
- ExecuteEvent(eventId);
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- }
-
- DoSpellAttackIfReady(SPELL_ARCANE_BOLT);
}
- private:
- bool _canUseArcaneExplosion;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<boss_high_nethermancer_zerevorAI>(creature);
+ DoSpellAttackIfReady(SPELL_ARCANE_BOLT);
}
+private:
+ bool _canUseArcaneExplosion;
};
-class boss_lady_malande : public CreatureScript
+struct boss_lady_malande : public IllidariCouncilBossAI
{
-public:
- boss_lady_malande() : CreatureScript("boss_lady_malande") { }
+ boss_lady_malande(Creature* creature) : IllidariCouncilBossAI(creature, DATA_LADY_MALANDE) { }
- struct boss_lady_malandeAI : public IllidariCouncilBossAI
+ void ScheduleEvents() override
{
- boss_lady_malandeAI(Creature* creature) : IllidariCouncilBossAI(creature, DATA_LADY_MALANDE) { }
+ events.ScheduleEvent(EVENT_CIRCLE_OF_HEALING, Seconds(20));
+ events.ScheduleEvent(EVENT_REFLECTIVE_SHIELD, Seconds(25));
+ events.ScheduleEvent(EVENT_DIVINE_WRATH, Seconds(32));
+ }
- void ScheduleEvents() override
- {
- events.ScheduleEvent(EVENT_CIRCLE_OF_HEALING, Seconds(20));
- events.ScheduleEvent(EVENT_REFLECTIVE_SHIELD, Seconds(25));
- events.ScheduleEvent(EVENT_DIVINE_WRATH, Seconds(32));
- }
+ void HealReceived(Unit* /*who*/, uint32& addhealth) override
+ {
+ // Need be negative to heal trigger
+ int32 bp = addhealth * (-1);
+ me->CastCustomSpell(SPELL_SHARED_RULE, SPELLVALUE_BASE_POINT0, bp, (Unit*) nullptr, true);
+ }
- void HealReceived(Unit* /*who*/, uint32& addhealth) override
- {
- // Need be negative to heal trigger
- int32 bp = addhealth * (-1);
- me->CastCustomSpell(SPELL_SHARED_RULE, SPELLVALUE_BASE_POINT0, bp, (Unit*) nullptr, true);
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
+ {
+ case EVENT_CIRCLE_OF_HEALING:
+ DoCastSelf(SPELL_CIRCLE_OF_HEALING);
+ events.Repeat(Seconds(20), Seconds(35));
+ break;
+ case EVENT_REFLECTIVE_SHIELD:
+ DoCastSelf(SPELL_REFLECTIVE_SHIELD);
+ Talk(SAY_COUNCIL_SPECIAL);
+ events.Repeat(Seconds(40));
+ break;
+ case EVENT_DIVINE_WRATH:
+ DoCastVictim(SPELL_DIVINE_WRATH);
+ events.Repeat(Seconds(20));
+ break;
+ default:
+ break;
}
+ }
- void ExecuteEvent(uint32 eventId) override
- {
- switch (eventId)
- {
- case EVENT_CIRCLE_OF_HEALING:
- DoCastSelf(SPELL_CIRCLE_OF_HEALING);
- events.Repeat(Seconds(20), Seconds(35));
- break;
- case EVENT_REFLECTIVE_SHIELD:
- DoCastSelf(SPELL_REFLECTIVE_SHIELD);
- Talk(SAY_COUNCIL_SPECIAL);
- events.Repeat(Seconds(40));
- break;
- case EVENT_DIVINE_WRATH:
- DoCastVictim(SPELL_DIVINE_WRATH);
- events.Repeat(Seconds(20));
- break;
- default:
- break;
- }
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ events.Update(diff);
- events.Update(diff);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ ExecuteEvent(eventId);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
-
- while (uint32 eventId = events.ExecuteEvent())
- {
- ExecuteEvent(eventId);
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- }
-
- DoSpellAttackIfReady(SPELL_EMPOWERED_SMITE);
}
- };
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<boss_lady_malandeAI>(creature);
+ DoSpellAttackIfReady(SPELL_EMPOWERED_SMITE);
}
-
};
-class boss_veras_darkshadow : public CreatureScript
+struct boss_veras_darkshadow : public IllidariCouncilBossAI
{
-public:
- boss_veras_darkshadow() : CreatureScript("boss_veras_darkshadow") { }
-
- struct boss_veras_darkshadowAI : public IllidariCouncilBossAI
+ boss_veras_darkshadow(Creature* creature) : IllidariCouncilBossAI(creature, DATA_VERAS_DARKSHADOW)
{
- boss_veras_darkshadowAI(Creature* creature) : IllidariCouncilBossAI(creature, DATA_VERAS_DARKSHADOW)
- {
- me->SetMaxHealth(1327900);
- me->SetFullHealth();
- }
-
- void ScheduleEvents() override
- {
- events.ScheduleEvent(EVENT_DEADLY_STRIKE, Seconds(18));
- events.ScheduleEvent(EVENT_VANISH, Seconds(18));
- }
+ me->SetMaxHealth(1327900);
+ me->SetFullHealth();
+ }
- void ExecuteEvent(uint32 eventId) override
- {
- switch (eventId)
- {
- case EVENT_DEADLY_STRIKE:
- DoCastSelf(SPELL_DEADLY_STRIKE);
- events.Repeat(Seconds(60));
- break;
- case EVENT_VANISH:
- DoCastSelf(SPELL_VANISH);
- Talk(SAY_COUNCIL_SPECIAL);
- events.Repeat(Seconds(60));
- break;
- default:
- break;
- }
- }
- };
+ void ScheduleEvents() override
+ {
+ events.ScheduleEvent(EVENT_DEADLY_STRIKE, Seconds(18));
+ events.ScheduleEvent(EVENT_VANISH, Seconds(18));
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void ExecuteEvent(uint32 eventId) override
{
- return GetBlackTempleAI<boss_veras_darkshadowAI>(creature);
+ switch (eventId)
+ {
+ case EVENT_DEADLY_STRIKE:
+ DoCastSelf(SPELL_DEADLY_STRIKE);
+ events.Repeat(Seconds(60));
+ break;
+ case EVENT_VANISH:
+ DoCastSelf(SPELL_VANISH);
+ Talk(SAY_COUNCIL_SPECIAL);
+ events.Repeat(Seconds(60));
+ break;
+ default:
+ break;
+ }
}
};
-class npc_veras_vanish_effect : public CreatureScript
+struct npc_veras_vanish_effect : public PassiveAI
{
-public:
- npc_veras_vanish_effect() : CreatureScript("npc_veras_vanish_effect") { }
-
- struct npc_veras_vanish_effectAI : public PassiveAI
- {
- npc_veras_vanish_effectAI(Creature* creature) : PassiveAI(creature) { }
-
- void Reset() override
- {
- DoCastSelf(SPELL_BIRTH, true);
- DoCastSelf(SPELL_ENVENOM_DUMMY, true);
- }
- };
+ npc_veras_vanish_effect(Creature* creature) : PassiveAI(creature) { }
- CreatureAI* GetAI(Creature* creature) const override
+ void Reset() override
{
- return GetBlackTempleAI<npc_veras_vanish_effectAI>(creature);
+ DoCastSelf(SPELL_BIRTH, true);
+ DoCastSelf(SPELL_ENVENOM_DUMMY, true);
}
};
// 41499 - Empyreal Balance
-class spell_illidari_council_empyreal_balance : public SpellScriptLoader
+class spell_illidari_council_empyreal_balance : public SpellScript
{
- public:
- spell_illidari_council_empyreal_balance() : SpellScriptLoader("spell_illidari_council_empyreal_balance") { }
-
- class spell_illidari_council_empyreal_balance_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_illidari_council_empyreal_balance_SpellScript);
-
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo({ SPELL_BALANCE_OF_POWER });
- }
+ PrepareSpellScript(spell_illidari_council_empyreal_balance);
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- Unit* target = GetHitUnit();
- target->CastSpell(target, SPELL_BALANCE_OF_POWER, true);
- }
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_BALANCE_OF_POWER });
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_illidari_council_empyreal_balance_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ Unit* target = GetHitUnit();
+ target->CastSpell(target, SPELL_BALANCE_OF_POWER, true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_illidari_council_empyreal_balance_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_illidari_council_empyreal_balance::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
// 41333 - Empyreal Equivalency
-class spell_illidari_council_empyreal_equivalency : public SpellScriptLoader
+class spell_illidari_council_empyreal_equivalency : public SpellScript
{
- public:
- spell_illidari_council_empyreal_equivalency() : SpellScriptLoader("spell_illidari_council_empyreal_equivalency") { }
+ PrepareSpellScript(spell_illidari_council_empyreal_equivalency);
- class spell_illidari_council_empyreal_equivalency_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_illidari_council_empyreal_equivalency_SpellScript);
-
- void HandleScript(SpellEffIndex /*effIndex*/)
- {
- Unit* target = GetHitUnit();
- int32 casterHpPct = (int32) GetCaster()->GetHealthPct();
- uint32 newHp = target->CountPctFromMaxHealth(casterHpPct);
- if (newHp <= 0)
- newHp = target->GetMaxHealth() - 1;
- target->SetHealth(newHp);
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_illidari_council_empyreal_equivalency_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Unit* target = GetHitUnit();
+ int32 casterHpPct = (int32)GetCaster()->GetHealthPct();
+ uint32 newHp = target->CountPctFromMaxHealth(casterHpPct);
+ if (newHp <= 0)
+ newHp = target->GetMaxHealth() - 1;
+ target->SetHealth(newHp);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_illidari_council_empyreal_equivalency_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_illidari_council_empyreal_equivalency::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
// 41341 - Balance of Power
-class spell_illidari_council_balance_of_power : public SpellScriptLoader
+class spell_illidari_council_balance_of_power : public AuraScript
{
- public:
- spell_illidari_council_balance_of_power() : SpellScriptLoader("spell_illidari_council_balance_of_power") { }
+ PrepareAuraScript(spell_illidari_council_balance_of_power);
- class spell_illidari_council_balance_of_power_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_illidari_council_balance_of_power_AuraScript);
-
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo({ SPELL_SHARED_RULE });
- }
-
- void Absorb(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& /*absorbAmount*/)
- {
- PreventDefaultAction();
- int32 bp = dmgInfo.GetDamage();
- GetTarget()->CastCustomSpell(SPELL_SHARED_RULE, SPELLVALUE_BASE_POINT0, bp, (Unit*) nullptr, true, nullptr, aurEff);
- }
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SHARED_RULE });
+ }
- void Register() override
- {
- OnEffectAbsorb += AuraEffectAbsorbFn(spell_illidari_council_balance_of_power_AuraScript::Absorb, EFFECT_0);
- }
- };
+ void Absorb(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& /*absorbAmount*/)
+ {
+ PreventDefaultAction();
+ int32 bp = dmgInfo.GetDamage();
+ GetTarget()->CastCustomSpell(SPELL_SHARED_RULE, SPELLVALUE_BASE_POINT0, bp, (Unit*) nullptr, true, nullptr, aurEff);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_illidari_council_balance_of_power_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectAbsorb += AuraEffectAbsorbFn(spell_illidari_council_balance_of_power::Absorb, EFFECT_0);
+ }
};
// 41480 - Deadly Strike
-class spell_illidari_council_deadly_strike : public SpellScriptLoader
+class spell_illidari_council_deadly_strike : public AuraScript
{
- public:
- spell_illidari_council_deadly_strike() : SpellScriptLoader("spell_illidari_council_deadly_strike") { }
-
- class spell_illidari_council_deadly_strike_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_illidari_council_deadly_strike_AuraScript);
+ PrepareAuraScript(spell_illidari_council_deadly_strike);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_DEADLY_POISON });
- }
-
- void OnTrigger(AuraEffect const* aurEff)
- {
- PreventDefaultAction();
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_DEADLY_POISON });
+ }
- if (Unit* victim = GetTarget()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0))
- GetTarget()->CastSpell(victim, SPELL_DEADLY_POISON, true, nullptr, aurEff);
- }
+ void OnTrigger(AuraEffect const* aurEff)
+ {
+ PreventDefaultAction();
- void Register() override
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidari_council_deadly_strike_AuraScript::OnTrigger, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
- }
- };
+ if (Unit* victim = GetTarget()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0))
+ GetTarget()->CastSpell(victim, SPELL_DEADLY_POISON, true, nullptr, aurEff);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_illidari_council_deadly_strike_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidari_council_deadly_strike::OnTrigger, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
};
// 41485 - Deadly Poison
-class spell_illidari_council_deadly_poison : public SpellScriptLoader
+class spell_illidari_council_deadly_poison : public AuraScript
{
- public:
- spell_illidari_council_deadly_poison() : SpellScriptLoader("spell_illidari_council_deadly_poison") { }
-
- class spell_illidari_council_deadly_poison_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_illidari_council_deadly_poison_AuraScript);
+ PrepareAuraScript(spell_illidari_council_deadly_poison);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_ENVENOM });
- }
-
- void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- if (Unit* caster = GetCaster())
- caster->CastSpell(GetTarget(), SPELL_ENVENOM, true);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_ENVENOM });
+ }
- void Register() override
- {
- OnEffectRemove += AuraEffectRemoveFn(spell_illidari_council_deadly_poison_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
- }
- };
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* caster = GetCaster())
+ caster->CastSpell(GetTarget(), SPELL_ENVENOM, true);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_illidari_council_deadly_poison_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectRemove += AuraEffectRemoveFn(spell_illidari_council_deadly_poison::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
+ }
};
// 41475 - Reflective Shield
-class spell_illidari_council_reflective_shield : public SpellScriptLoader
+class spell_illidari_council_reflective_shield : public AuraScript
{
- public:
- spell_illidari_council_reflective_shield() : SpellScriptLoader("spell_illidari_council_reflective_shield") { }
+ PrepareAuraScript(spell_illidari_council_reflective_shield);
- class spell_illidari_council_reflective_shield_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_illidari_council_reflective_shield_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_REFLECTIVE_SHIELD_DAMAGE });
- }
-
- void OnAbsorb(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount)
- {
- Unit* target = GetTarget();
- if (dmgInfo.GetAttacker() == target)
- return;
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_REFLECTIVE_SHIELD_DAMAGE });
+ }
- int32 bp = absorbAmount / 2;
- target->CastCustomSpell(dmgInfo.GetAttacker(), SPELL_REFLECTIVE_SHIELD_DAMAGE, &bp, nullptr, nullptr, true, nullptr, aurEff);
- }
+ void OnAbsorb(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount)
+ {
+ Unit* target = GetTarget();
+ if (dmgInfo.GetAttacker() == target)
+ return;
- void Register() override
- {
- AfterEffectAbsorb += AuraEffectAbsorbFn(spell_illidari_council_reflective_shield_AuraScript::OnAbsorb, EFFECT_0);
- }
- };
+ int32 bp = absorbAmount / 2;
+ target->CastCustomSpell(dmgInfo.GetAttacker(), SPELL_REFLECTIVE_SHIELD_DAMAGE, &bp, nullptr, nullptr, true, nullptr, aurEff);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_illidari_council_reflective_shield_AuraScript();
- }
+ void Register() override
+ {
+ AfterEffectAbsorb += AuraEffectAbsorbFn(spell_illidari_council_reflective_shield::OnAbsorb, EFFECT_0);
+ }
};
// 41467 - Judgement
-class spell_illidari_council_judgement : public SpellScriptLoader
+class spell_illidari_council_judgement : public SpellScript
{
- public:
- spell_illidari_council_judgement() : SpellScriptLoader("spell_illidari_council_judgement") { }
+ PrepareSpellScript(spell_illidari_council_judgement);
- class spell_illidari_council_judgement_SpellScript : public SpellScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareSpellScript(spell_illidari_council_judgement_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_JUDGEMENT_OF_BLOOD,
- SPELL_JUDGEMENT_OF_COMMAND,
- SPELL_JUDGEMENT_PRIMER
- });
- }
-
- void HandleScript(SpellEffIndex /*effIndex*/)
- {
- Unit* caster = GetCaster();
- Unit* target = GetHitUnit();
- uint32 judgementId = caster->HasAura(SPELL_SEAL_OF_BLOOD) ? SPELL_JUDGEMENT_OF_BLOOD : SPELL_JUDGEMENT_OF_COMMAND;
- caster->CastSpell(target, SPELL_JUDGEMENT_PRIMER, true);
- caster->CastSpell(target, judgementId, true);
- }
+ SPELL_JUDGEMENT_OF_BLOOD,
+ SPELL_JUDGEMENT_OF_COMMAND,
+ SPELL_JUDGEMENT_PRIMER
+ });
+ }
- void OnFinishCast()
- {
- if (Creature* caster = GetCaster()->ToCreature())
- caster->AI()->Talk(SAY_COUNCIL_SPECIAL);
- }
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ Unit* target = GetHitUnit();
+ uint32 judgementId = caster->HasAura(SPELL_SEAL_OF_BLOOD) ? SPELL_JUDGEMENT_OF_BLOOD : SPELL_JUDGEMENT_OF_COMMAND;
+ caster->CastSpell(target, SPELL_JUDGEMENT_PRIMER, true);
+ caster->CastSpell(target, judgementId, true);
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_illidari_council_judgement_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- AfterCast += SpellCastFn(spell_illidari_council_judgement_SpellScript::OnFinishCast);
- }
- };
+ void OnFinishCast()
+ {
+ if (Creature* caster = GetCaster()->ToCreature())
+ caster->AI()->Talk(SAY_COUNCIL_SPECIAL);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_illidari_council_judgement_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_illidari_council_judgement::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ AfterCast += SpellCastFn(spell_illidari_council_judgement::OnFinishCast);
+ }
};
/* 41469 - Seal of Command
41459 - Seal of Blood */
-class spell_illidari_council_seal : public SpellScriptLoader
+class spell_illidari_council_seal : public AuraScript
{
- public:
- spell_illidari_council_seal() : SpellScriptLoader("spell_illidari_council_seal") { }
+ PrepareAuraScript(spell_illidari_council_seal);
- class spell_illidari_council_seal_AuraScript : public AuraScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareAuraScript(spell_illidari_council_seal_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_SEAL_OF_COMMAND,
- SPELL_SEAL_OF_BLOOD
- });
- }
-
- void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
- {
- Unit* target = GetTarget();
- if (target->IsInWorld() && target->IsAlive())
- {
- uint32 spellId = aurEff->GetId() == SPELL_SEAL_OF_COMMAND ? SPELL_SEAL_OF_BLOOD : SPELL_SEAL_OF_COMMAND;
- target->CastSpell(target, spellId, true);
- }
- }
-
- void Register() override
- {
- OnEffectRemove += AuraEffectRemoveFn(spell_illidari_council_seal_AuraScript::OnRemove, EFFECT_2, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
- }
- };
+ SPELL_SEAL_OF_COMMAND,
+ SPELL_SEAL_OF_BLOOD
+ });
+ }
- AuraScript* GetAuraScript() const override
+ void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* target = GetTarget();
+ if (target->IsInWorld() && target->IsAlive())
{
- return new spell_illidari_council_seal_AuraScript();
+ uint32 spellId = aurEff->GetId() == SPELL_SEAL_OF_COMMAND ? SPELL_SEAL_OF_BLOOD : SPELL_SEAL_OF_COMMAND;
+ target->CastSpell(target, spellId, true);
}
+ }
+
+ void Register() override
+ {
+ OnEffectRemove += AuraEffectRemoveFn(spell_illidari_council_seal::OnRemove, EFFECT_2, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
};
// 41478 - Dampen Magic
-class spell_illidari_dampen_magic : public SpellScriptLoader
+class spell_illidari_dampen_magic : public AuraScript
{
- public:
- spell_illidari_dampen_magic() : SpellScriptLoader("spell_illidari_dampen_magic") { }
-
- class spell_illidari_dampen_magic_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_illidari_dampen_magic_AuraScript);
-
- void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- if (Creature* target = GetTarget()->ToCreature())
- {
- AuraRemoveMode mode = GetTargetApplication()->GetRemoveMode();
- if (mode == AURA_REMOVE_BY_ENEMY_SPELL || mode == AURA_REMOVE_BY_EXPIRE)
- target->AI()->DoAction(ACTION_REFRESH_DAMPEN);
- }
- }
-
- void Register() override
- {
- OnEffectRemove += AuraEffectRemoveFn(spell_illidari_dampen_magic_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL);
- }
- };
+ PrepareAuraScript(spell_illidari_dampen_magic);
- AuraScript* GetAuraScript() const override
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Creature* target = GetTarget()->ToCreature())
{
- return new spell_illidari_dampen_magic_AuraScript();
+ AuraRemoveMode mode = GetTargetApplication()->GetRemoveMode();
+ if (mode == AURA_REMOVE_BY_ENEMY_SPELL || mode == AURA_REMOVE_BY_EXPIRE)
+ target->AI()->DoAction(ACTION_REFRESH_DAMPEN);
}
+ }
+
+ void Register() override
+ {
+ OnEffectRemove += AuraEffectRemoveFn(spell_illidari_dampen_magic::OnRemove, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL);
+ }
};
void AddSC_boss_illidari_council()
{
- new boss_illidari_council();
- new boss_gathios_the_shatterer();
- new boss_lady_malande();
- new boss_veras_darkshadow();
- new boss_high_nethermancer_zerevor();
- new npc_veras_vanish_effect();
- new spell_illidari_council_empyreal_balance();
- new spell_illidari_council_empyreal_equivalency();
- new spell_illidari_council_balance_of_power();
- new spell_illidari_council_deadly_strike();
- new spell_illidari_council_deadly_poison();
- new spell_illidari_council_reflective_shield();
- new spell_illidari_council_judgement();
- new spell_illidari_council_seal();
- new spell_illidari_dampen_magic();
+ RegisterBlackTempleCreatureAI(boss_illidari_council);
+ RegisterBlackTempleCreatureAI(boss_gathios_the_shatterer);
+ RegisterBlackTempleCreatureAI(boss_lady_malande);
+ RegisterBlackTempleCreatureAI(boss_veras_darkshadow);
+ RegisterBlackTempleCreatureAI(boss_high_nethermancer_zerevor);
+ RegisterBlackTempleCreatureAI(npc_veras_vanish_effect);
+ RegisterSpellScript(spell_illidari_council_empyreal_balance);
+ RegisterSpellScript(spell_illidari_council_empyreal_equivalency);
+ RegisterAuraScript(spell_illidari_council_balance_of_power);
+ RegisterAuraScript(spell_illidari_council_deadly_strike);
+ RegisterAuraScript(spell_illidari_council_deadly_poison);
+ RegisterAuraScript(spell_illidari_council_reflective_shield);
+ RegisterSpellScript(spell_illidari_council_judgement);
+ RegisterAuraScript(spell_illidari_council_seal);
+ RegisterAuraScript(spell_illidari_dampen_magic);
}
diff --git a/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp b/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp
index 38fa695c5db..fdd79cf92ea 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp
@@ -107,299 +107,233 @@ Position const TeleportPoint[7]=
{ 965.997f, 278.398f, 195.777f }
};
-class boss_mother_shahraz : public CreatureScript
+struct boss_mother_shahraz : public BossAI
{
-public:
- boss_mother_shahraz() : CreatureScript("boss_mother_shahraz") { }
+ boss_mother_shahraz(Creature* creature) : BossAI(creature, DATA_MOTHER_SHAHRAZ), _enraged(false) { }
- struct boss_shahrazAI : public BossAI
+ void Reset() override
{
- boss_shahrazAI(Creature* creature) : BossAI(creature, DATA_MOTHER_SHAHRAZ), _enraged(false) { }
+ _Reset();
+ _enraged = false;
+ }
- void Reset() override
- {
- _Reset();
- _enraged = false;
- }
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _EnterCombat();
+ Talk(SAY_AGGRO);
+ events.ScheduleEvent(EVENT_SILENCING_SHRIEK, Seconds(22));
+ events.ScheduleEvent(EVENT_PRISMATIC_SHIELD, Seconds(15));
+ events.ScheduleEvent(EVENT_FATAL_ATTRACTION, Seconds(35));
+ events.ScheduleEvent(EVENT_RANDOM_BEAM, Seconds(6));
+ events.ScheduleEvent(EVENT_BERSERK, Minutes(10));
+ events.ScheduleEvent(EVENT_TAUNT, Seconds(35));
+ }
- void EnterCombat(Unit* /*who*/) override
- {
- _EnterCombat();
- Talk(SAY_AGGRO);
- events.ScheduleEvent(EVENT_SILENCING_SHRIEK, Seconds(22));
- events.ScheduleEvent(EVENT_PRISMATIC_SHIELD, Seconds(15));
- events.ScheduleEvent(EVENT_FATAL_ATTRACTION, Seconds(35));
- events.ScheduleEvent(EVENT_RANDOM_BEAM, Seconds(6));
- events.ScheduleEvent(EVENT_BERSERK, Minutes(10));
- events.ScheduleEvent(EVENT_TAUNT, Seconds(35));
- }
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SLAY);
+ }
- void KilledUnit(Unit* victim) override
- {
- if (victim->GetTypeId() == TYPEID_PLAYER)
- Talk(SAY_SLAY);
- }
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ Talk(SAY_DEATH);
+ }
- void JustDied(Unit* /*killer*/) override
- {
- _JustDied();
- Talk(SAY_DEATH);
- }
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ _DespawnAtEvade();
+ }
- void EnterEvadeMode(EvadeReason /*why*/) override
+ void DamageTaken(Unit* /*attacker*/, uint32 &damage) override
+ {
+ if (!_enraged && me->HealthBelowPctDamaged(10, damage))
{
- _DespawnAtEvade();
+ _enraged = true;
+ DoCastSelf(SPELL_RANDOM_PERIODIC, true);
+ Talk(EMOTE_ENRAGE, me);
+ Talk(SAY_ENRAGE);
}
+ }
- void DamageTaken(Unit* /*attacker*/, uint32 &damage) override
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
{
- if (!_enraged && me->HealthBelowPctDamaged(10, damage))
- {
- _enraged = true;
- DoCastSelf(SPELL_RANDOM_PERIODIC, true);
- Talk(EMOTE_ENRAGE, me);
- Talk(SAY_ENRAGE);
- }
+ case EVENT_RANDOM_BEAM:
+ DoCastSelf(BeamTriggers[urand(0, 3)]);
+ events.Repeat(Seconds(30));
+ break;
+ case EVENT_PRISMATIC_SHIELD:
+ DoCastSelf(PrismaticAuras[urand(0, 5)]);
+ events.Repeat(Seconds(15));
+ break;
+ case EVENT_FATAL_ATTRACTION:
+ Talk(SAY_SPELL);
+ me->CastCustomSpell(SPELL_FATAL_ATTACTION_TELEPORT, SPELLVALUE_MAX_TARGETS, 3, me);
+ events.Repeat(Seconds(30));
+ break;
+ case EVENT_SILENCING_SHRIEK:
+ DoCastVictim(SPELL_SILENCING_SHRIEK);
+ events.Repeat(Seconds(18), Seconds(30));
+ break;
+ case EVENT_TAUNT:
+ Talk(SAY_TAUNT);
+ events.Repeat(Seconds(30), Seconds(40));
+ break;
+ case EVENT_BERSERK:
+ Talk(EMOTE_BERSERK, me);
+ DoCastSelf(SPELL_BERSERK);
+ break;
+ default:
+ break;
}
+ }
- void ExecuteEvent(uint32 eventId) override
+private:
+ bool _enraged;
+};
+
+// 40869 - Fatal Attraction
+class spell_mother_shahraz_fatal_attraction : public SpellScript
+{
+ PrepareSpellScript(spell_mother_shahraz_fatal_attraction);
+
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo(
{
- switch (eventId)
- {
- case EVENT_RANDOM_BEAM:
- DoCastSelf(BeamTriggers[urand(0, 3)]);
- events.Repeat(Seconds(30));
- break;
- case EVENT_PRISMATIC_SHIELD:
- DoCastSelf(PrismaticAuras[urand(0, 5)]);
- events.Repeat(Seconds(15));
- break;
- case EVENT_FATAL_ATTRACTION:
- Talk(SAY_SPELL);
- me->CastCustomSpell(SPELL_FATAL_ATTACTION_TELEPORT, SPELLVALUE_MAX_TARGETS, 3, me);
- events.Repeat(Seconds(30));
- break;
- case EVENT_SILENCING_SHRIEK:
- DoCastVictim(SPELL_SILENCING_SHRIEK);
- events.Repeat(Seconds(18), Seconds(30));
- break;
- case EVENT_TAUNT:
- Talk(SAY_TAUNT);
- events.Repeat(Seconds(30), Seconds(40));
- break;
- case EVENT_BERSERK:
- Talk(EMOTE_BERSERK, me);
- DoCastSelf(SPELL_BERSERK);
- break;
- default:
- break;
- }
- }
+ SPELL_SABER_LASH_IMMUNITY,
+ SPELL_FATAL_ATTRACTION
+ });
+ }
- private:
- bool _enraged;
- };
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_SABER_LASH_IMMUNITY));
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void SetDest(SpellDestination& dest)
{
- return GetBlackTempleAI<boss_shahrazAI>(creature);
+ dest.Relocate(TeleportPoint[urand(0, 6)]);
}
-};
-// 40869 - Fatal Attraction
-class spell_mother_shahraz_fatal_attraction : public SpellScriptLoader
-{
- public:
- spell_mother_shahraz_fatal_attraction() : SpellScriptLoader("spell_mother_shahraz_fatal_attraction") { }
+ void HandleTeleport(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->CastSpell(GetHitUnit(), SPELL_FATAL_ATTRACTION, true);
+ }
- class spell_mother_shahraz_fatal_attraction_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_mother_shahraz_fatal_attraction_SpellScript);
-
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_SABER_LASH_IMMUNITY,
- SPELL_FATAL_ATTRACTION
- });
- }
-
- void FilterTargets(std::list<WorldObject*>& targets)
- {
- targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_SABER_LASH_IMMUNITY));
- }
-
- void SetDest(SpellDestination& dest)
- {
- dest.Relocate(TeleportPoint[urand(0, 6)]);
- }
-
- void HandleTeleport(SpellEffIndex /*effIndex*/)
- {
- GetCaster()->CastSpell(GetHitUnit(), SPELL_FATAL_ATTRACTION, true);
- }
-
- void Register() override
- {
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mother_shahraz_fatal_attraction_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
- OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_mother_shahraz_fatal_attraction_SpellScript::SetDest, EFFECT_1, TARGET_DEST_CASTER_RANDOM);
- OnEffectHitTarget += SpellEffectFn(spell_mother_shahraz_fatal_attraction_SpellScript::HandleTeleport, EFFECT_1, SPELL_EFFECT_TELEPORT_UNITS);
- }
- };
-
- SpellScript* GetSpellScript() const override
- {
- return new spell_mother_shahraz_fatal_attraction_SpellScript();
- }
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mother_shahraz_fatal_attraction::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_mother_shahraz_fatal_attraction::SetDest, EFFECT_1, TARGET_DEST_CASTER_RANDOM);
+ OnEffectHitTarget += SpellEffectFn(spell_mother_shahraz_fatal_attraction::HandleTeleport, EFFECT_1, SPELL_EFFECT_TELEPORT_UNITS);
+ }
};
// 40870 - Fatal Attraction Dummy Visual
-class spell_mother_shahraz_fatal_attraction_link : public SpellScriptLoader
+class spell_mother_shahraz_fatal_attraction_link : public SpellScript
{
- public:
- spell_mother_shahraz_fatal_attraction_link() : SpellScriptLoader("spell_mother_shahraz_fatal_attraction_link") { }
-
- class spell_mother_shahraz_fatal_attraction_link_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_mother_shahraz_fatal_attraction_link_SpellScript);
+ PrepareSpellScript(spell_mother_shahraz_fatal_attraction_link);
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo({ SPELL_FATAL_ATTRACTION_DAMAGE });
- }
-
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- GetCaster()->CastSpell(GetCaster(), SPELL_FATAL_ATTRACTION_DAMAGE, true);
- }
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_FATAL_ATTRACTION_DAMAGE });
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_mother_shahraz_fatal_attraction_link_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->CastSpell(GetCaster(), SPELL_FATAL_ATTRACTION_DAMAGE, true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_mother_shahraz_fatal_attraction_link_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_mother_shahraz_fatal_attraction_link::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
// 40816 - Saber Lash
-class spell_mother_shahraz_saber_lash : public SpellScriptLoader
+class spell_mother_shahraz_saber_lash : public AuraScript
{
- public:
- spell_mother_shahraz_saber_lash() : SpellScriptLoader("spell_mother_shahraz_saber_lash") { }
-
- class spell_mother_shahraz_saber_lash_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_mother_shahraz_saber_lash_AuraScript);
+ PrepareAuraScript(spell_mother_shahraz_saber_lash);
- bool Validate(SpellInfo const* spellInfo) override
- {
- return ValidateSpellInfo({ spellInfo->Effects[EFFECT_1].TriggerSpell });
- }
-
- void OnTrigger(AuraEffect const* aurEff)
- {
- PreventDefaultAction();
+ bool Validate(SpellInfo const* spellInfo) override
+ {
+ return ValidateSpellInfo({ spellInfo->Effects[EFFECT_1].TriggerSpell });
+ }
- uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell;
- if (Unit* target = GetUnitOwner()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0))
- GetUnitOwner()->CastSpell(target, triggerSpell, true);
- }
+ void OnTrigger(AuraEffect const* aurEff)
+ {
+ PreventDefaultAction();
- void Register() override
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_mother_shahraz_saber_lash_AuraScript::OnTrigger, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
- }
- };
+ uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell;
+ if (Unit* target = GetUnitOwner()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0))
+ GetUnitOwner()->CastSpell(target, triggerSpell, true);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_mother_shahraz_saber_lash_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_mother_shahraz_saber_lash::OnTrigger, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
};
/* 40863 - Sinister Periodic
40865 - Vile Periodic
40866 - Wicked Periodic
40862 - Sinful Periodic */
-class spell_mother_shahraz_generic_periodic : public SpellScriptLoader
+class spell_mother_shahraz_generic_periodic : public AuraScript
{
- public:
- spell_mother_shahraz_generic_periodic() : SpellScriptLoader("spell_mother_shahraz_generic_periodic") { }
-
- class spell_mother_shahraz_generic_periodic_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_mother_shahraz_generic_periodic_AuraScript);
-
- bool Validate(SpellInfo const* spellInfo) override
- {
- return ValidateSpellInfo({ spellInfo->Effects[EFFECT_0].TriggerSpell });
- }
+ PrepareAuraScript(spell_mother_shahraz_generic_periodic);
- void OnTrigger(AuraEffect const* aurEff)
- {
- PreventDefaultAction();
+ bool Validate(SpellInfo const* spellInfo) override
+ {
+ return ValidateSpellInfo({ spellInfo->Effects[EFFECT_0].TriggerSpell });
+ }
- uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell;
- if (Unit* target = GetUnitOwner()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0))
- GetUnitOwner()->CastSpell(target, triggerSpell, true);
- }
+ void OnTrigger(AuraEffect const* aurEff)
+ {
+ PreventDefaultAction();
- void Register() override
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_mother_shahraz_generic_periodic_AuraScript::OnTrigger, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
- }
- };
+ uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell;
+ if (Unit* target = GetUnitOwner()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0))
+ GetUnitOwner()->CastSpell(target, triggerSpell, true);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_mother_shahraz_generic_periodic_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_mother_shahraz_generic_periodic::OnTrigger, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
};
// 40867 - Random Periodic
-class spell_mother_shahraz_random_periodic : public SpellScriptLoader
+class spell_mother_shahraz_random_periodic : public AuraScript
{
- public:
- spell_mother_shahraz_random_periodic() : SpellScriptLoader("spell_mother_shahraz_random_periodic") { }
+ PrepareAuraScript(spell_mother_shahraz_random_periodic);
- class spell_mother_shahraz_random_periodic_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_mother_shahraz_random_periodic_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(RandomBeam);
- }
-
- void OnPeriodic(AuraEffect const* /*aurEffect*/)
- {
- PreventDefaultAction();
- GetUnitOwner()->CastSpell(GetUnitOwner(), RandomBeam[urand(0, 3)], true);
- }
-
- void Register() override
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_mother_shahraz_random_periodic_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
- }
- };
-
- AuraScript* GetAuraScript() const override
- {
- return new spell_mother_shahraz_random_periodic_AuraScript();
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(RandomBeam);
+ }
+
+ void OnPeriodic(AuraEffect const* /*aurEffect*/)
+ {
+ PreventDefaultAction();
+ GetUnitOwner()->CastSpell(GetUnitOwner(), RandomBeam[urand(0, 3)], true);
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_mother_shahraz_random_periodic::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
};
void AddSC_boss_mother_shahraz()
{
- new boss_mother_shahraz();
- new spell_mother_shahraz_fatal_attraction();
- new spell_mother_shahraz_fatal_attraction_link();
- new spell_mother_shahraz_saber_lash();
- new spell_mother_shahraz_generic_periodic();
- new spell_mother_shahraz_random_periodic();
+ RegisterBlackTempleCreatureAI(boss_mother_shahraz);
+ RegisterSpellScript(spell_mother_shahraz_fatal_attraction);
+ RegisterSpellScript(spell_mother_shahraz_fatal_attraction_link);
+ RegisterAuraScript(spell_mother_shahraz_saber_lash);
+ RegisterAuraScript(spell_mother_shahraz_generic_periodic);
+ RegisterAuraScript(spell_mother_shahraz_random_periodic);
}
diff --git a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp
index ae3d961ca68..c069482f139 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp
@@ -136,737 +136,638 @@ class EnslavedSoulEvent : public BasicEvent
Creature* _owner;
};
-class boss_reliquary_of_souls : public CreatureScript
+struct boss_reliquary_of_souls : public BossAI
{
-public:
- boss_reliquary_of_souls() : CreatureScript("boss_reliquary_of_souls") { }
+ boss_reliquary_of_souls(Creature* creature) : BossAI(creature, DATA_RELIQUARY_OF_SOULS), _inCombat(false)
+ {
+ creature->m_SightDistance = 70.0f;
+ }
- struct boss_reliquary_of_soulsAI : public BossAI
+ void Reset() override
{
- boss_reliquary_of_soulsAI(Creature* creature) : BossAI(creature, DATA_RELIQUARY_OF_SOULS), _inCombat(false)
- {
- creature->m_SightDistance = 70.0f;
- }
+ _Reset();
+ me->SetReactState(REACT_PASSIVE);
+ _inCombat = false;
+ events.SetPhase(PHASE_ESSENCE_OF_SUFFERING);
+ }
- void Reset() override
+ void MoveInLineOfSight(Unit* who) override
+ {
+ if (!_inCombat && who->GetTypeId() == TYPEID_PLAYER && !who->ToPlayer()->IsGameMaster() && CanAIAttack(who))
{
- _Reset();
- me->SetReactState(REACT_PASSIVE);
- _inCombat = false;
- events.SetPhase(PHASE_ESSENCE_OF_SUFFERING);
+ _inCombat = true;
+ DoZoneInCombat();
+ me->SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_STAND_STATE, UNIT_STAND_STATE_STAND);
+ events.ScheduleEvent(EVENT_SUBMERGE, Seconds(10));
}
+ }
- void MoveInLineOfSight(Unit* who) override
- {
- if (!_inCombat && who->GetTypeId() == TYPEID_PLAYER && !who->ToPlayer()->IsGameMaster() && CanAIAttack(who))
- {
- _inCombat = true;
- DoZoneInCombat();
- me->SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_STAND_STATE, UNIT_STAND_STATE_STAND);
- events.ScheduleEvent(EVENT_SUBMERGE, Seconds(10));
- }
- }
+ uint32 GetSummonSpell()
+ {
+ if (events.IsInPhase(PHASE_ESSENCE_OF_SUFFERING))
+ return SPELL_SUMMON_ESSENCE_OF_SUFFERING;
+ else if (events.IsInPhase(PHASE_ESSENCE_OF_DESIRE))
+ return SPELL_SUMMON_ESSENCE_OF_DESIRE;
+ else if (events.IsInPhase(PHASE_ESSENCE_OF_ANGER))
+ return SPELL_SUMMON_ESSENCE_OF_ANGER;
+ else //Should never happen
+ return 0;
+ }
- uint32 GetSummonSpell()
- {
- if (events.IsInPhase(PHASE_ESSENCE_OF_SUFFERING))
- return SPELL_SUMMON_ESSENCE_OF_SUFFERING;
- else if (events.IsInPhase(PHASE_ESSENCE_OF_DESIRE))
- return SPELL_SUMMON_ESSENCE_OF_DESIRE;
- else if (events.IsInPhase(PHASE_ESSENCE_OF_ANGER))
- return SPELL_SUMMON_ESSENCE_OF_ANGER;
- else //Should never happen
- return 0;
+ void DoAction(int32 actionId) override
+ {
+ switch (actionId)
+ {
+ case ACTION_ESSENCE_OF_SUFFERING_DEAD:
+ me->RemoveAurasDueToSpell(SPELL_SUBMERGE_VISUAL);
+ events.SetPhase(PHASE_ESSENCE_OF_DESIRE);
+ HandleSpirits();
+ events.ScheduleEvent(EVENT_SUBMERGE, Seconds(40));
+ break;
+ case ACTION_ESSENCE_OF_DESIRE_DEAD:
+ me->RemoveAurasDueToSpell(SPELL_SUBMERGE_VISUAL);
+ events.SetPhase(PHASE_ESSENCE_OF_ANGER);
+ HandleSpirits();
+ events.ScheduleEvent(EVENT_SUBMERGE, Seconds(40));
+ break;
+ case ACTION_KILL_SELF:
+ me->KillSelf();
+ break;
}
+ }
- void DoAction(int32 actionId) override
- {
- switch (actionId)
- {
- case ACTION_ESSENCE_OF_SUFFERING_DEAD:
- me->RemoveAurasDueToSpell(SPELL_SUBMERGE_VISUAL);
- events.SetPhase(PHASE_ESSENCE_OF_DESIRE);
- HandleSpirits();
- events.ScheduleEvent(EVENT_SUBMERGE, Seconds(40));
- break;
- case ACTION_ESSENCE_OF_DESIRE_DEAD:
- me->RemoveAurasDueToSpell(SPELL_SUBMERGE_VISUAL);
- events.SetPhase(PHASE_ESSENCE_OF_ANGER);
- HandleSpirits();
- events.ScheduleEvent(EVENT_SUBMERGE, Seconds(40));
- break;
- case ACTION_KILL_SELF:
- me->KillSelf();
- break;
- }
+ void HandleSpirits()
+ {
+ std::vector<Creature*> _worldTriggerList;
+ me->GetCreatureListWithEntryInGrid(_worldTriggerList, NPC_RELIQUARY_WORLD_TRIGGER, 70.0f);
+
+ if (_worldTriggerList.empty())
+ return;
+
+ //Get random creatures
+ Trinity::Containers::RandomShuffle(_worldTriggerList);
+ _worldTriggerList.resize(21);
+
+ for (uint8 i = 0; i < 21; i++)
+ {
+ Creature* wTrigger = _worldTriggerList[i];
+ if (i < 3)
+ wTrigger->m_Events.AddEvent(new EnslavedSoulEvent(wTrigger), wTrigger->m_Events.CalculateTime(4000));
+ else if (i < 6)
+ wTrigger->m_Events.AddEvent(new EnslavedSoulEvent(wTrigger), wTrigger->m_Events.CalculateTime(8000));
+ else if (i < 9)
+ wTrigger->m_Events.AddEvent(new EnslavedSoulEvent(wTrigger), wTrigger->m_Events.CalculateTime(12000));
+ else if (i < 12)
+ wTrigger->m_Events.AddEvent(new EnslavedSoulEvent(wTrigger), wTrigger->m_Events.CalculateTime(16000));
+ else if (i < 15)
+ wTrigger->m_Events.AddEvent(new EnslavedSoulEvent(wTrigger), wTrigger->m_Events.CalculateTime(20000));
+ else if (i < 18)
+ wTrigger->m_Events.AddEvent(new EnslavedSoulEvent(wTrigger), wTrigger->m_Events.CalculateTime(24000));
+ else
+ wTrigger->m_Events.AddEvent(new EnslavedSoulEvent(wTrigger), wTrigger->m_Events.CalculateTime(28000));
}
+ }
- void HandleSpirits()
- {
- std::vector<Creature*> _worldTriggerList;
- me->GetCreatureListWithEntryInGrid(_worldTriggerList, NPC_RELIQUARY_WORLD_TRIGGER, 70.0f);
-
- if (_worldTriggerList.empty())
- return;
+ void KillAssyncEvents()
+ {
+ std::vector<Creature*> _worldTriggerList;
+ me->GetCreatureListWithEntryInGrid(_worldTriggerList, NPC_RELIQUARY_WORLD_TRIGGER, 70.0f);
- //Get random creatures
- Trinity::Containers::RandomShuffle(_worldTriggerList);
- _worldTriggerList.resize(21);
+ if (_worldTriggerList.empty())
+ return;
- for (uint8 i = 0; i < 21; i++)
- {
- Creature* wTrigger = _worldTriggerList[i];
- if (i < 3)
- wTrigger->m_Events.AddEvent(new EnslavedSoulEvent(wTrigger), wTrigger->m_Events.CalculateTime(4000));
- else if (i < 6)
- wTrigger->m_Events.AddEvent(new EnslavedSoulEvent(wTrigger), wTrigger->m_Events.CalculateTime(8000));
- else if (i < 9)
- wTrigger->m_Events.AddEvent(new EnslavedSoulEvent(wTrigger), wTrigger->m_Events.CalculateTime(12000));
- else if (i < 12)
- wTrigger->m_Events.AddEvent(new EnslavedSoulEvent(wTrigger), wTrigger->m_Events.CalculateTime(16000));
- else if (i < 15)
- wTrigger->m_Events.AddEvent(new EnslavedSoulEvent(wTrigger), wTrigger->m_Events.CalculateTime(20000));
- else if (i < 18)
- wTrigger->m_Events.AddEvent(new EnslavedSoulEvent(wTrigger), wTrigger->m_Events.CalculateTime(24000));
- else
- wTrigger->m_Events.AddEvent(new EnslavedSoulEvent(wTrigger), wTrigger->m_Events.CalculateTime(28000));
- }
- }
+ for (Creature* trigger : _worldTriggerList)
+ trigger->m_Events.KillAllEvents(true);
+ }
- void KillAssyncEvents()
- {
- std::vector<Creature*> _worldTriggerList;
- me->GetCreatureListWithEntryInGrid(_worldTriggerList, NPC_RELIQUARY_WORLD_TRIGGER, 70.0f);
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ events.Reset();
+ summons.DespawnAll();
+ KillAssyncEvents();
+ _DespawnAtEvade();
+ }
- if (_worldTriggerList.empty())
- return;
+ void JustDied(Unit* /*killer*/) override
+ {
+ events.Reset();
+ instance->SetBossState(DATA_RELIQUARY_OF_SOULS, DONE);
+ }
- for (Creature* trigger : _worldTriggerList)
- trigger->m_Events.KillAllEvents(true);
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- void EnterEvadeMode(EvadeReason /*why*/) override
- {
- events.Reset();
- summons.DespawnAll();
- KillAssyncEvents();
- _DespawnAtEvade();
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- void JustDied(Unit* /*killer*/) override
- {
- events.Reset();
- instance->SetBossState(DATA_RELIQUARY_OF_SOULS, DONE);
- }
+ events.Update(diff);
- void UpdateAI(uint32 diff) override
+ while (uint32 eventId = events.ExecuteEvent())
{
- if (!UpdateVictim())
- return;
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- events.Update(diff);
-
- while (uint32 eventId = events.ExecuteEvent())
+ switch (eventId)
{
- switch (eventId)
+ case EVENT_SUBMERGE:
+ DoCastSelf(SPELL_SUBMERGE_VISUAL, true);
+ events.ScheduleEvent(EVENT_SUMMON_ESSENCE, Seconds(3));
+ break;
+ case EVENT_SUMMON_ESSENCE:
{
- case EVENT_SUBMERGE:
- DoCastSelf(SPELL_SUBMERGE_VISUAL, true);
- events.ScheduleEvent(EVENT_SUMMON_ESSENCE, Seconds(3));
- break;
- case EVENT_SUMMON_ESSENCE:
- {
- EntryCheckPredicate pred(NPC_ENSLAVED_SOUL);
- summons.DoAction(ACTION_KILL_SELF, pred);
- DoCastSelf(GetSummonSpell());
- break;
- }
- default:
- break;
+ EntryCheckPredicate pred(NPC_ENSLAVED_SOUL);
+ summons.DoAction(ACTION_KILL_SELF, pred);
+ DoCastSelf(GetSummonSpell());
+ break;
}
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ default:
+ break;
}
- }
-
- private:
- bool _inCombat;
- };
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<boss_reliquary_of_soulsAI>(creature);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
}
+
+private:
+ bool _inCombat;
};
-class boss_essence_of_suffering : public CreatureScript
+struct boss_essence_of_suffering : public BossAI
{
-public:
- boss_essence_of_suffering() : CreatureScript("boss_essence_of_suffering") { }
+ boss_essence_of_suffering(Creature* creature) : BossAI(creature, DATA_ESSENCE_OF_SUFFERING), _dead(false)
+ {
+ SetBoundary(instance->GetBossBoundary(DATA_RELIQUARY_OF_SOULS));
+ }
- struct boss_essence_of_sufferingAI : public BossAI
+ void Reset() override
{
- boss_essence_of_sufferingAI(Creature* creature) : BossAI(creature, DATA_ESSENCE_OF_SUFFERING), _dead(false)
- {
- SetBoundary(instance->GetBossBoundary(DATA_RELIQUARY_OF_SOULS));
- }
+ DoCastAOE(SPELL_AURA_OF_SUFFERING, true);
+ events.Reset();
+ _dead = false;
+ }
- void Reset() override
- {
- DoCastAOE(SPELL_AURA_OF_SUFFERING, true);
- events.Reset();
- _dead = false;
- }
+ void MovementInform(uint32 motionType, uint32 pointId) override
+ {
+ if (motionType != POINT_MOTION_TYPE)
+ return;
- void MovementInform(uint32 motionType, uint32 pointId) override
+ if (pointId == RELIQUARY_DESPAWN_WAYPOINT)
{
- if (motionType != POINT_MOTION_TYPE)
- return;
-
- if (pointId == RELIQUARY_DESPAWN_WAYPOINT)
- {
- if (Creature* reliquary = instance->GetCreature(DATA_RELIQUARY_OF_SOULS))
- reliquary->AI()->DoAction(ACTION_ESSENCE_OF_SUFFERING_DEAD);
+ if (Creature* reliquary = instance->GetCreature(DATA_RELIQUARY_OF_SOULS))
+ reliquary->AI()->DoAction(ACTION_ESSENCE_OF_SUFFERING_DEAD);
- DoCastSelf(SPELL_SUBMERGE_VISUAL, true);
- me->DespawnOrUnsummon(Seconds(2));
- }
+ DoCastSelf(SPELL_SUBMERGE_VISUAL, true);
+ me->DespawnOrUnsummon(Seconds(2));
}
+ }
- void DamageTaken(Unit* /*done_by*/, uint32 &damage) override
+ void DamageTaken(Unit* /*done_by*/, uint32 &damage) override
+ {
+ if (damage >= me->GetHealth())
{
- if (damage >= me->GetHealth())
+ damage = 0;
+ if (!_dead)
{
- damage = 0;
- if (!_dead)
- {
- _dead = true;
- Talk(SUFF_SAY_RECAP);
- me->AttackStop();
- me->SetReactState(REACT_PASSIVE);
- events.Reset();
- me->InterruptNonMeleeSpells(false);
- me->GetMotionMaster()->MovePoint(RELIQUARY_DESPAWN_WAYPOINT, DespawnPoint);
- }
+ _dead = true;
+ Talk(SUFF_SAY_RECAP);
+ me->AttackStop();
+ me->SetReactState(REACT_PASSIVE);
+ events.Reset();
+ me->InterruptNonMeleeSpells(false);
+ me->GetMotionMaster()->MovePoint(RELIQUARY_DESPAWN_WAYPOINT, DespawnPoint);
}
}
+ }
- void EnterCombat(Unit* /*who*/) override
- {
- me->SetCombatPulseDelay(5);
- me->setActive(true);
- DoZoneInCombat();
+ void EnterCombat(Unit* /*who*/) override
+ {
+ me->SetCombatPulseDelay(5);
+ me->setActive(true);
+ DoZoneInCombat();
- events.ScheduleEvent(EVENT_SOUL_DRAIN, Seconds(20));
- events.ScheduleEvent(EVENT_FRENZY, Seconds(45));
- Talk(SUFF_SAY_AGRO);
- }
+ events.ScheduleEvent(EVENT_SOUL_DRAIN, Seconds(20));
+ events.ScheduleEvent(EVENT_FRENZY, Seconds(45));
+ Talk(SUFF_SAY_AGRO);
+ }
- void KilledUnit(Unit* victim) override
- {
- if (victim->GetTypeId() == TYPEID_PLAYER)
- Talk(SUFF_SAY_SLAY);
- }
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SUFF_SAY_SLAY);
+ }
- void EnterEvadeMode(EvadeReason /*why*/) override
- {
- if (Creature* reliquary = instance->GetCreature(DATA_RELIQUARY_OF_SOULS))
- reliquary->AI()->EnterEvadeMode(EVADE_REASON_OTHER);
- }
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ if (Creature* reliquary = instance->GetCreature(DATA_RELIQUARY_OF_SOULS))
+ reliquary->AI()->EnterEvadeMode(EVADE_REASON_OTHER);
+ }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- events.Update(diff);
+ events.Update(diff);
- while (uint32 eventId = events.ExecuteEvent())
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- switch (eventId)
- {
- case EVENT_SOUL_DRAIN:
- me->CastCustomSpell(SPELL_SOUL_DRAIN, SPELLVALUE_MAX_TARGETS, 5, me);
- events.Repeat(Seconds(30), Seconds(35));
- break;
- case EVENT_FRENZY:
- Talk(SUFF_SAY_ENRAGE);
- DoCastSelf(SPELL_FRENZY);
- events.Repeat(Seconds(45), Seconds(50));
- break;
- default:
- break;
- }
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ case EVENT_SOUL_DRAIN:
+ me->CastCustomSpell(SPELL_SOUL_DRAIN, SPELLVALUE_MAX_TARGETS, 5, me);
+ events.Repeat(Seconds(30), Seconds(35));
+ break;
+ case EVENT_FRENZY:
+ Talk(SUFF_SAY_ENRAGE);
+ DoCastSelf(SPELL_FRENZY);
+ events.Repeat(Seconds(45), Seconds(50));
+ break;
+ default:
+ break;
}
- DoMeleeAttackIfReady();
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
- private:
- bool _dead;
- };
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<boss_essence_of_sufferingAI>(creature);
+ DoMeleeAttackIfReady();
}
+private:
+ bool _dead;
};
-class boss_essence_of_desire : public CreatureScript
+struct boss_essence_of_desire : public BossAI
{
-public:
- boss_essence_of_desire() : CreatureScript("boss_essence_of_desire") { }
-
- struct boss_essence_of_desireAI : public BossAI
+ boss_essence_of_desire(Creature* creature) : BossAI(creature, DATA_ESSENCE_OF_DESIRE), _dead(false)
{
- boss_essence_of_desireAI(Creature* creature) : BossAI(creature, DATA_ESSENCE_OF_DESIRE), _dead(false)
- {
- SetBoundary(instance->GetBossBoundary(DATA_RELIQUARY_OF_SOULS));
- }
+ SetBoundary(instance->GetBossBoundary(DATA_RELIQUARY_OF_SOULS));
+ }
- void Reset() override
- {
- DoCastSelf(SPELL_AURA_OF_DESIRE, true);
- events.Reset();
- _dead = false;
- }
+ void Reset() override
+ {
+ DoCastSelf(SPELL_AURA_OF_DESIRE, true);
+ events.Reset();
+ _dead = false;
+ }
- void EnterCombat(Unit* /*who*/) override
- {
- events.ScheduleEvent(EVENT_SPIRIT_SHOCK, Seconds(11));
- events.ScheduleEvent(EVENT_RUNE_SHIELD, Seconds(16));
- events.ScheduleEvent(EVENT_DEADEN, Seconds(31));
+ void EnterCombat(Unit* /*who*/) override
+ {
+ events.ScheduleEvent(EVENT_SPIRIT_SHOCK, Seconds(11));
+ events.ScheduleEvent(EVENT_RUNE_SHIELD, Seconds(16));
+ events.ScheduleEvent(EVENT_DEADEN, Seconds(31));
+
+ me->SetCombatPulseDelay(5);
+ me->setActive(true);
+ DoZoneInCombat();
+ Talk(DESI_SAY_FREED);
+ }
- me->SetCombatPulseDelay(5);
- me->setActive(true);
- DoZoneInCombat();
- Talk(DESI_SAY_FREED);
- }
+ void MovementInform(uint32 motionType, uint32 pointId) override
+ {
+ if (motionType != POINT_MOTION_TYPE)
+ return;
- void MovementInform(uint32 motionType, uint32 pointId) override
+ if (pointId == RELIQUARY_DESPAWN_WAYPOINT)
{
- if (motionType != POINT_MOTION_TYPE)
- return;
-
- if (pointId == RELIQUARY_DESPAWN_WAYPOINT)
- {
- if (Creature* reliquary = instance->GetCreature(DATA_RELIQUARY_OF_SOULS))
- reliquary->AI()->DoAction(ACTION_ESSENCE_OF_DESIRE_DEAD);
+ if (Creature* reliquary = instance->GetCreature(DATA_RELIQUARY_OF_SOULS))
+ reliquary->AI()->DoAction(ACTION_ESSENCE_OF_DESIRE_DEAD);
- DoCastSelf(SPELL_SUBMERGE_VISUAL, true);
- me->DespawnOrUnsummon(Seconds(2));
- }
+ DoCastSelf(SPELL_SUBMERGE_VISUAL, true);
+ me->DespawnOrUnsummon(Seconds(2));
}
+ }
- void DamageTaken(Unit* /*done_by*/, uint32 &damage) override
+ void DamageTaken(Unit* /*done_by*/, uint32 &damage) override
+ {
+ if (damage >= me->GetHealth())
{
- if (damage >= me->GetHealth())
+ damage = 0;
+ if (!_dead)
{
- damage = 0;
- if (!_dead)
- {
- _dead = true;
- Talk(DESI_SAY_RECAP);
- me->AttackStop();
- me->SetReactState(REACT_PASSIVE);
- events.Reset();
- me->InterruptNonMeleeSpells(false);
- me->GetMotionMaster()->MovePoint(RELIQUARY_DESPAWN_WAYPOINT, DespawnPoint);
- }
+ _dead = true;
+ Talk(DESI_SAY_RECAP);
+ me->AttackStop();
+ me->SetReactState(REACT_PASSIVE);
+ events.Reset();
+ me->InterruptNonMeleeSpells(false);
+ me->GetMotionMaster()->MovePoint(RELIQUARY_DESPAWN_WAYPOINT, DespawnPoint);
}
}
+ }
- void KilledUnit(Unit* victim) override
- {
- if (victim->GetTypeId() == TYPEID_PLAYER)
- Talk(DESI_SAY_SLAY);
- }
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(DESI_SAY_SLAY);
+ }
- void EnterEvadeMode(EvadeReason /*why*/) override
- {
- if (Creature* reliquary = instance->GetCreature(DATA_RELIQUARY_OF_SOULS))
- reliquary->AI()->EnterEvadeMode(EVADE_REASON_OTHER);
- }
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ if (Creature* reliquary = instance->GetCreature(DATA_RELIQUARY_OF_SOULS))
+ reliquary->AI()->EnterEvadeMode(EVADE_REASON_OTHER);
+ }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- events.Update(diff);
+ events.Update(diff);
- while (uint32 eventId = events.ExecuteEvent())
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- switch (eventId)
- {
- case EVENT_SPIRIT_SHOCK:
- DoCastVictim(SPELL_SPIRIT_SHOCK);
- events.Repeat(Seconds(10), Seconds(15));
- break;
- case EVENT_RUNE_SHIELD:
- DoCastSelf(SPELL_RUNE_SHIELD);
- events.Repeat(Seconds(16));
- break;
- case EVENT_DEADEN:
- Talk(DESI_SAY_SPEC);
- DoCastVictim(SPELL_DEADEN);
- events.Repeat(Seconds(31));
- break;
- default:
- break;
- }
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ case EVENT_SPIRIT_SHOCK:
+ DoCastVictim(SPELL_SPIRIT_SHOCK);
+ events.Repeat(Seconds(10), Seconds(15));
+ break;
+ case EVENT_RUNE_SHIELD:
+ DoCastSelf(SPELL_RUNE_SHIELD);
+ events.Repeat(Seconds(16));
+ break;
+ case EVENT_DEADEN:
+ Talk(DESI_SAY_SPEC);
+ DoCastVictim(SPELL_DEADEN);
+ events.Repeat(Seconds(31));
+ break;
+ default:
+ break;
}
- DoMeleeAttackIfReady();
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
- private:
- bool _dead;
- };
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<boss_essence_of_desireAI>(creature);
+ DoMeleeAttackIfReady();
}
+private:
+ bool _dead;
};
-class boss_essence_of_anger : public CreatureScript
+struct boss_essence_of_anger : public BossAI
{
-public:
- boss_essence_of_anger() : CreatureScript("boss_essence_of_anger") { }
-
- struct boss_essence_of_angerAI : public BossAI
+ boss_essence_of_anger(Creature* creature) :BossAI(creature, DATA_ESSENCE_OF_ANGER)
{
- boss_essence_of_angerAI(Creature* creature) :BossAI(creature, DATA_ESSENCE_OF_ANGER)
- {
- SetBoundary(instance->GetBossBoundary(DATA_RELIQUARY_OF_SOULS));
- }
+ SetBoundary(instance->GetBossBoundary(DATA_RELIQUARY_OF_SOULS));
+ }
- void Reset() override
- {
- events.Reset();
- _targetGUID.Clear();
- DoCastSelf(SPELL_AURA_OF_ANGER);
- }
+ void Reset() override
+ {
+ events.Reset();
+ _targetGUID.Clear();
+ DoCastSelf(SPELL_AURA_OF_ANGER);
+ }
- void EnterCombat(Unit* /*who*/) override
- {
- Talk(ANGER_SAY_FREED);
+ void EnterCombat(Unit* /*who*/) override
+ {
+ Talk(ANGER_SAY_FREED);
- events.ScheduleEvent(EVENT_START_CHECK_TANKER, Seconds(5));
- events.ScheduleEvent(EVENT_SOUL_SCREAM, Seconds(11));
- events.ScheduleEvent(EVENT_SPITE, Seconds(20));
- events.ScheduleEvent(EVENT_FREED_2, Seconds(1), Minutes(3));
+ events.ScheduleEvent(EVENT_START_CHECK_TANKER, Seconds(5));
+ events.ScheduleEvent(EVENT_SOUL_SCREAM, Seconds(11));
+ events.ScheduleEvent(EVENT_SPITE, Seconds(20));
+ events.ScheduleEvent(EVENT_FREED_2, Seconds(1), Minutes(3));
- me->SetCombatPulseDelay(5);
- me->setActive(true);
- DoZoneInCombat();
- }
+ me->SetCombatPulseDelay(5);
+ me->setActive(true);
+ DoZoneInCombat();
+ }
- void JustDied(Unit* /*killer*/) override
- {
- DoPlaySoundToSet(me, ANGER_SOUND_ID_DEATH);
- if (Creature* reliquary = instance->GetCreature(DATA_RELIQUARY_OF_SOULS))
- reliquary->AI()->DoAction(ACTION_KILL_SELF);
- }
+ void JustDied(Unit* /*killer*/) override
+ {
+ DoPlaySoundToSet(me, ANGER_SOUND_ID_DEATH);
+ if (Creature* reliquary = instance->GetCreature(DATA_RELIQUARY_OF_SOULS))
+ reliquary->AI()->DoAction(ACTION_KILL_SELF);
+ }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- events.Update(diff);
+ events.Update(diff);
- while (uint32 eventId = events.ExecuteEvent())
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- switch (eventId)
+ case EVENT_CHECK_TANKER:
{
- case EVENT_CHECK_TANKER:
+ Unit* target = me->GetVictim();
+ if (!_targetGUID || !target)
+ return;
+
+ if (target->GetGUID() != _targetGUID)
{
- Unit* target = me->GetVictim();
- if (!_targetGUID || !target)
- return;
-
- if (target->GetGUID() != _targetGUID)
- {
- Talk(ANGER_SAY_SEETHE);
- Talk(ANGER_EMOTE_SEETHE, me);
- _targetGUID = target->GetGUID();
- DoCastSelf(SPELL_SEETHE, true);
- }
- break;
+ Talk(ANGER_SAY_SEETHE);
+ Talk(ANGER_EMOTE_SEETHE, me);
+ _targetGUID = target->GetGUID();
+ DoCastSelf(SPELL_SEETHE, true);
}
- case EVENT_SOUL_SCREAM:
- DoCastSelf(SPELL_SOUL_SCREAM);
- events.Repeat(Seconds(11));
- break;
- case EVENT_SPITE:
- Talk(ANGER_SAY_SPITE);
- me->CastCustomSpell(SPELL_SPITE, SPELLVALUE_MAX_TARGETS, 3, me);
- events.Repeat(Seconds(20));
- break;
- case EVENT_START_CHECK_TANKER:
- if (Unit* target = me->GetVictim())
- {
- _targetGUID = target->GetGUID();
- events.ScheduleEvent(EVENT_CHECK_TANKER, Seconds(1));
- }
- else
- events.Repeat(Seconds(1));
- break;
- case EVENT_FREED_2:
- Talk(ANGER_SAY_FREED_2);
- break;
- default:
- break;
+ break;
}
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ case EVENT_SOUL_SCREAM:
+ DoCastSelf(SPELL_SOUL_SCREAM);
+ events.Repeat(Seconds(11));
+ break;
+ case EVENT_SPITE:
+ Talk(ANGER_SAY_SPITE);
+ me->CastCustomSpell(SPELL_SPITE, SPELLVALUE_MAX_TARGETS, 3, me);
+ events.Repeat(Seconds(20));
+ break;
+ case EVENT_START_CHECK_TANKER:
+ if (Unit* target = me->GetVictim())
+ {
+ _targetGUID = target->GetGUID();
+ events.ScheduleEvent(EVENT_CHECK_TANKER, Seconds(1));
+ }
+ else
+ events.Repeat(Seconds(1));
+ break;
+ case EVENT_FREED_2:
+ Talk(ANGER_SAY_FREED_2);
+ break;
+ default:
+ break;
}
- DoMeleeAttackIfReady();
- }
-
- void EnterEvadeMode(EvadeReason /*why*/) override
- {
- if (Creature* reliquary = instance->GetCreature(DATA_RELIQUARY_OF_SOULS))
- reliquary->AI()->EnterEvadeMode(EVADE_REASON_OTHER);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
- private:
- ObjectGuid _targetGUID;
- };
+ DoMeleeAttackIfReady();
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void EnterEvadeMode(EvadeReason /*why*/) override
{
- return GetBlackTempleAI<boss_essence_of_angerAI>(creature);
+ if (Creature* reliquary = instance->GetCreature(DATA_RELIQUARY_OF_SOULS))
+ reliquary->AI()->EnterEvadeMode(EVADE_REASON_OTHER);
}
+
+private:
+ ObjectGuid _targetGUID;
};
-class npc_enslaved_soul : public CreatureScript
+struct npc_enslaved_soul : public ScriptedAI
{
-public:
- npc_enslaved_soul() : CreatureScript("npc_enslaved_soul") { }
+ npc_enslaved_soul(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
- struct npc_enslaved_soulAI : public ScriptedAI
+ void Reset() override
{
- npc_enslaved_soulAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
-
- void Reset() override
- {
- me->SetReactState(REACT_PASSIVE);
- if (Creature* reliquary = _instance->GetCreature(DATA_RELIQUARY_OF_SOULS))
- reliquary->AI()->JustSummoned(me);
+ me->SetReactState(REACT_PASSIVE);
+ if (Creature* reliquary = _instance->GetCreature(DATA_RELIQUARY_OF_SOULS))
+ reliquary->AI()->JustSummoned(me);
- DoCastSelf(SPELL_ENSLAVED_SOUL_PASSIVE, true);
+ DoCastSelf(SPELL_ENSLAVED_SOUL_PASSIVE, true);
- _scheduler.Schedule(Seconds(3), [this](TaskContext /*context*/)
- {
- me->SetReactState(REACT_AGGRESSIVE);
- me->SetInCombatWithZone();
- });
- }
-
- void DoAction(int32 actionId) override
+ _scheduler.Schedule(Seconds(3), [this](TaskContext /*context*/)
{
- if (actionId == ACTION_KILL_SELF)
- me->KillSelf();
- }
+ me->SetReactState(REACT_AGGRESSIVE);
+ me->SetInCombatWithZone();
+ });
+ }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ void DoAction(int32 actionId) override
+ {
+ if (actionId == ACTION_KILL_SELF)
+ me->KillSelf();
+ }
- _scheduler.Update(diff);
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- DoMeleeAttackIfReady();
- }
+ _scheduler.Update(diff);
- void JustDied(Unit* /*killer*/) override
- {
- DoCastSelf(SPELL_SOUL_RELEASE, true);
- }
-
- private:
- InstanceScript* _instance;
- TaskScheduler _scheduler;
- };
+ DoMeleeAttackIfReady();
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void JustDied(Unit* /*killer*/) override
{
- return GetBlackTempleAI<npc_enslaved_soulAI>(creature);
+ DoCastSelf(SPELL_SOUL_RELEASE, true);
}
+
+private:
+ InstanceScript* _instance;
+ TaskScheduler _scheduler;
};
// 41350 - Aura of Desire
-class spell_reliquary_of_souls_aura_of_desire : public SpellScriptLoader
+class spell_reliquary_of_souls_aura_of_desire : public AuraScript
{
- public:
- spell_reliquary_of_souls_aura_of_desire() : SpellScriptLoader("spell_reliquary_of_souls_aura_of_desire") { }
-
- class spell_reliquary_of_souls_aura_of_desire_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_reliquary_of_souls_aura_of_desire_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_AURA_OF_DESIRE_DAMAGE });
- }
+ PrepareAuraScript(spell_reliquary_of_souls_aura_of_desire);
- void OnProcSpell(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
- DamageInfo* damageInfo = eventInfo.GetDamageInfo();
- if (!damageInfo || !damageInfo->GetDamage())
- return;
-
- Unit* caster = eventInfo.GetActor();
- int32 bp = damageInfo->GetDamage() / 2;
- caster->CastCustomSpell(SPELL_AURA_OF_DESIRE_DAMAGE, SPELLVALUE_BASE_POINT0, bp, caster, true, nullptr, aurEff);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_AURA_OF_DESIRE_DAMAGE });
+ }
- void UpdateAmount(AuraEffect* /*aurEff*/)
- {
- if (AuraEffect* effect = GetAura()->GetEffect(EFFECT_1))
- effect->ChangeAmount(effect->GetAmount() - 5);
- }
+ void OnProcSpell(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+ DamageInfo* damageInfo = eventInfo.GetDamageInfo();
+ if (!damageInfo || !damageInfo->GetDamage())
+ return;
+
+ Unit* caster = eventInfo.GetActor();
+ int32 bp = damageInfo->GetDamage() / 2;
+ caster->CastCustomSpell(SPELL_AURA_OF_DESIRE_DAMAGE, SPELLVALUE_BASE_POINT0, bp, caster, true, nullptr, aurEff);
+ }
- void Register() override
- {
- OnEffectProc += AuraEffectProcFn(spell_reliquary_of_souls_aura_of_desire_AuraScript::OnProcSpell, EFFECT_0, SPELL_AURA_MOD_HEALING_PCT);
- OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_reliquary_of_souls_aura_of_desire_AuraScript::UpdateAmount, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
- }
- };
+ void UpdateAmount(AuraEffect* /*aurEff*/)
+ {
+ if (AuraEffect* effect = GetAura()->GetEffect(EFFECT_1))
+ effect->ChangeAmount(effect->GetAmount() - 5);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_reliquary_of_souls_aura_of_desire_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_reliquary_of_souls_aura_of_desire::OnProcSpell, EFFECT_0, SPELL_AURA_MOD_HEALING_PCT);
+ OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_reliquary_of_souls_aura_of_desire::UpdateAmount, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
};
// 28819 - Submerge Visual
-class spell_reliquary_of_souls_submerge : public SpellScriptLoader
+class spell_reliquary_of_souls_submerge : public AuraScript
{
- public:
- spell_reliquary_of_souls_submerge() : SpellScriptLoader("spell_reliquary_of_souls_submerge") { }
-
- class spell_reliquary_of_souls_submerge_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_reliquary_of_souls_submerge_AuraScript);
+ PrepareAuraScript(spell_reliquary_of_souls_submerge);
- void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- GetTarget()->SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_STAND_STATE, UNIT_STAND_STATE_SUBMERGED);
- }
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_STAND_STATE, UNIT_STAND_STATE_SUBMERGED);
+ }
- void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- GetTarget()->SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_STAND_STATE, UNIT_STAND_STATE_STAND);
- }
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_STAND_STATE, UNIT_STAND_STATE_STAND);
+ }
- void Register() override
- {
- AfterEffectApply += AuraEffectApplyFn(spell_reliquary_of_souls_submerge_AuraScript::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
- AfterEffectRemove += AuraEffectRemoveFn(spell_reliquary_of_souls_submerge_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
- }
- };
-
- AuraScript* GetAuraScript() const override
- {
- return new spell_reliquary_of_souls_submerge_AuraScript();
- }
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_reliquary_of_souls_submerge::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_reliquary_of_souls_submerge::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
};
// 41376 - Spite
-class spell_reliquary_of_souls_spite : public SpellScriptLoader
+class spell_reliquary_of_souls_spite : public AuraScript
{
- public:
- spell_reliquary_of_souls_spite() : SpellScriptLoader("spell_reliquary_of_souls_spite") { }
-
- class spell_reliquary_of_souls_spite_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_reliquary_of_souls_spite_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_SPITE_DAMAGE });
- }
+ PrepareAuraScript(spell_reliquary_of_souls_spite);
- void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- if (Unit* caster = GetCaster())
- caster->CastSpell(GetTarget(), SPELL_SPITE_DAMAGE, true);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SPITE_DAMAGE });
+ }
- void Register() override
- {
- AfterEffectRemove += AuraEffectRemoveFn(spell_reliquary_of_souls_spite_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DAMAGE_IMMUNITY, AURA_EFFECT_HANDLE_REAL);
- }
- };
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* caster = GetCaster())
+ caster->CastSpell(GetTarget(), SPELL_SPITE_DAMAGE, true);
+ }
- AuraScript* GetAuraScript() const
- {
- return new spell_reliquary_of_souls_spite_AuraScript();
- }
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_reliquary_of_souls_spite::OnRemove, EFFECT_0, SPELL_AURA_DAMAGE_IMMUNITY, AURA_EFFECT_HANDLE_REAL);
+ }
};
// 41305 - Frenzy
-class spell_reliquary_of_souls_frenzy : public SpellScriptLoader
+class spell_reliquary_of_souls_frenzy : public SpellScript
{
- public:
- spell_reliquary_of_souls_frenzy() : SpellScriptLoader("spell_reliquary_of_souls_frenzy") { }
-
- class spell_reliquary_of_souls_frenzy_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_reliquary_of_souls_frenzy_SpellScript);
-
- void HandleAfterCast()
- {
- if (Creature* caster = GetCaster()->ToCreature())
- caster->AI()->Talk(SUFF_EMOTE_ENRAGE, caster);
- }
+ PrepareSpellScript(spell_reliquary_of_souls_frenzy);
- void Register() override
- {
- AfterCast += SpellCastFn(spell_reliquary_of_souls_frenzy_SpellScript::HandleAfterCast);
- }
- };
+ void HandleAfterCast()
+ {
+ if (Creature* caster = GetCaster()->ToCreature())
+ caster->AI()->Talk(SUFF_EMOTE_ENRAGE, caster);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_reliquary_of_souls_frenzy_SpellScript();
- }
+ void Register() override
+ {
+ AfterCast += SpellCastFn(spell_reliquary_of_souls_frenzy::HandleAfterCast);
+ }
};
void AddSC_boss_reliquary_of_souls()
{
- new boss_reliquary_of_souls();
- new boss_essence_of_suffering();
- new boss_essence_of_desire();
- new boss_essence_of_anger();
- new npc_enslaved_soul();
- new spell_reliquary_of_souls_aura_of_desire();
- new spell_reliquary_of_souls_submerge();
- new spell_reliquary_of_souls_spite();
- new spell_reliquary_of_souls_frenzy();
+ RegisterBlackTempleCreatureAI(boss_reliquary_of_souls);
+ RegisterBlackTempleCreatureAI(boss_essence_of_suffering);
+ RegisterBlackTempleCreatureAI(boss_essence_of_desire);
+ RegisterBlackTempleCreatureAI(boss_essence_of_anger);
+ RegisterBlackTempleCreatureAI(npc_enslaved_soul);
+ RegisterAuraScript(spell_reliquary_of_souls_aura_of_desire);
+ RegisterAuraScript(spell_reliquary_of_souls_submerge);
+ RegisterAuraScript(spell_reliquary_of_souls_spite);
+ RegisterSpellScript(spell_reliquary_of_souls_frenzy);
}
diff --git a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp
index 41090701682..17fd7d91c21 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp
@@ -32,14 +32,14 @@
enum Says
{
// Akama
- SAY_BROKEN_FREE_0 = 0,
- SAY_BROKEN_FREE_1 = 1,
- SAY_BROKEN_FREE_2 = 2,
- SAY_LOW_HEALTH = 3,
- SAY_DEAD = 4,
+ SAY_BROKEN_FREE_0 = 0,
+ SAY_BROKEN_FREE_1 = 1,
+ SAY_BROKEN_FREE_2 = 2,
+ SAY_LOW_HEALTH = 3,
+ SAY_DEAD = 4,
// Ashtongue Broken
- SAY_BROKEN_SPECIAL = 0,
- SAY_BROKEN_HAIL = 1
+ SAY_BROKEN_SPECIAL = 0,
+ SAY_BROKEN_HAIL = 1
};
enum Spells
@@ -81,20 +81,20 @@ enum Spells
enum Creatures
{
- NPC_ASHTONGUE_CHANNELER = 23421,
- NPC_ASHTONGUE_BROKEN = 23319,
- NPC_CREATURE_SPAWNER_AKAMA = 23210
+ NPC_ASHTONGUE_CHANNELER = 23421,
+ NPC_ASHTONGUE_BROKEN = 23319,
+ NPC_CREATURE_SPAWNER_AKAMA = 23210
};
enum Actions
{
- ACTION_START_SPAWNING = 0,
- ACTION_STOP_SPAWNING = 1,
- ACTION_DESPAWN_ALL_SPAWNS = 2,
- ACTION_SHADE_OF_AKAMA_DEAD = 3,
- ACTION_BROKEN_SPECIAL = 4,
- ACTION_BROKEN_EMOTE = 5,
- ACTION_BROKEN_HAIL = 6
+ ACTION_START_SPAWNING = 0,
+ ACTION_STOP_SPAWNING = 1,
+ ACTION_DESPAWN_ALL_SPAWNS = 2,
+ ACTION_SHADE_OF_AKAMA_DEAD = 3,
+ ACTION_BROKEN_SPECIAL = 4,
+ ACTION_BROKEN_EMOTE = 5,
+ ACTION_BROKEN_HAIL = 6
};
enum Events
@@ -139,10 +139,9 @@ enum Events
enum Misc
{
- AKAMA_CHANNEL_WAYPOINT = 0,
- AKAMA_INTRO_WAYPOINT = 1,
-
- SUMMON_GROUP_RESET = 1
+ AKAMA_CHANNEL_WAYPOINT = 0,
+ AKAMA_INTRO_WAYPOINT = 1,
+ SUMMON_GROUP_RESET = 1
};
Position const AkamaWP[2] =
@@ -199,1073 +198,941 @@ static float const MIDDLE_OF_ROOM = 400.0f;
static float const FACE_THE_DOOR = 0.08726646f;
static float const FACE_THE_PLATFORM = 3.118662f;
-class boss_shade_of_akama : public CreatureScript
+
+struct boss_shade_of_akama : public BossAI
{
-public:
- boss_shade_of_akama() : CreatureScript("boss_shade_of_akama") { }
+ boss_shade_of_akama(Creature* creature) : BossAI(creature, DATA_SHADE_OF_AKAMA)
+ {
+ Initialize();
+ }
- struct boss_shade_of_akamaAI : public BossAI
+ void Initialize()
{
- boss_shade_of_akamaAI(Creature* creature) : BossAI(creature, DATA_SHADE_OF_AKAMA)
- {
- Initialize();
- }
+ _spawners.clear();
+ _isInPhaseOne = true;
+ }
- void Initialize()
- {
- _spawners.clear();
- _isInPhaseOne = true;
- }
+ void Reset() override
+ {
+ _Reset();
+ Initialize();
+ me->SetImmuneToPC(true);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN);
+ me->SetWalk(true);
+ events.ScheduleEvent(EVENT_INITIALIZE_SPAWNERS, Seconds(1));
+ me->SummonCreatureGroup(SUMMON_GROUP_RESET);
+ }
+
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ events.Reset();
+ summons.DespawnAll();
+
+ for (ObjectGuid const spawnerGuid : _spawners)
+ if (Creature* spawner = ObjectAccessor::GetCreature(*me, spawnerGuid))
+ spawner->AI()->DoAction(ACTION_DESPAWN_ALL_SPAWNS);
- void Reset() override
+ _DespawnAtEvade();
+ }
+
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
+ {
+ if (spell->Id == SPELL_AKAMA_SOUL_CHANNEL)
{
- _Reset();
- Initialize();
- me->SetImmuneToPC(true);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN);
- me->SetWalk(true);
- events.ScheduleEvent(EVENT_INITIALIZE_SPAWNERS, Seconds(1));
- me->SummonCreatureGroup(SUMMON_GROUP_RESET);
+ events.ScheduleEvent(EVENT_START_CHANNELERS_AND_SPAWNERS, Seconds(1));
+ me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE);
+ events.ScheduleEvent(EVENT_EVADE_CHECK, Seconds(10));
+ if (Creature* akama = instance->GetCreature(DATA_AKAMA_SHADE))
+ AttackStart(akama);
}
- void EnterEvadeMode(EvadeReason /*why*/) override
+ if (spell->Id == SPELL_AKAMA_SOUL_RETRIEVE)
+ DoCastSelf(SPELL_AKAMA_SOUL_EXPEL_CHANNEL);
+ }
+
+ void MovementInform(uint32 motionType, uint32 /*pointId*/) override
+ {
+ if (_isInPhaseOne && motionType == CHASE_MOTION_TYPE)
{
- events.Reset();
- summons.DespawnAll();
+ _isInPhaseOne = false;
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->SetImmuneToPC(false);
+ me->SetWalk(false);
+ events.ScheduleEvent(EVENT_ADD_THREAT, Milliseconds(100));
for (ObjectGuid const spawnerGuid : _spawners)
if (Creature* spawner = ObjectAccessor::GetCreature(*me, spawnerGuid))
- spawner->AI()->DoAction(ACTION_DESPAWN_ALL_SPAWNS);
-
- _DespawnAtEvade();
+ spawner->AI()->DoAction(ACTION_STOP_SPAWNING);
}
+ }
- void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
- {
- if (spell->Id == SPELL_AKAMA_SOUL_CHANNEL)
- {
- events.ScheduleEvent(EVENT_START_CHANNELERS_AND_SPAWNERS, Seconds(1));
- me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE);
- events.ScheduleEvent(EVENT_EVADE_CHECK, Seconds(10));
- if (Creature* akama = instance->GetCreature(DATA_AKAMA_SHADE))
- AttackStart(akama);
- }
-
- if (spell->Id == SPELL_AKAMA_SOUL_RETRIEVE)
- DoCastSelf(SPELL_AKAMA_SOUL_EXPEL_CHANNEL);
- }
+ void JustDied(Unit* /*killer*/) override
+ {
+ DoCastSelf(SPELL_SHADE_OF_AKAMA_TRIGGER);
- void MovementInform(uint32 motionType, uint32 /*pointId*/) override
- {
- if (_isInPhaseOne && motionType == CHASE_MOTION_TYPE)
- {
- _isInPhaseOne = false;
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetImmuneToPC(false);
- me->SetWalk(false);
- events.ScheduleEvent(EVENT_ADD_THREAT, Milliseconds(100));
-
- for (ObjectGuid const spawnerGuid : _spawners)
- if (Creature* spawner = ObjectAccessor::GetCreature(*me, spawnerGuid))
- spawner->AI()->DoAction(ACTION_STOP_SPAWNING);
- }
- }
+ if (Creature* akama = instance->GetCreature(DATA_AKAMA_SHADE))
+ akama->AI()->DoAction(ACTION_SHADE_OF_AKAMA_DEAD);
- void JustDied(Unit* /*killer*/) override
- {
- DoCastSelf(SPELL_SHADE_OF_AKAMA_TRIGGER);
+ for (ObjectGuid const spawnerGuid : _spawners)
+ if (Creature* spawner = ObjectAccessor::GetCreature(*me, spawnerGuid))
+ spawner->AI()->DoAction(ACTION_DESPAWN_ALL_SPAWNS);
- if (Creature* akama = instance->GetCreature(DATA_AKAMA_SHADE))
- akama->AI()->DoAction(ACTION_SHADE_OF_AKAMA_DEAD);
+ events.Reset();
+ summons.DespawnEntry(NPC_ASHTONGUE_CHANNELER);
+ instance->SetBossState(DATA_SHADE_OF_AKAMA, DONE);
+ }
- for (ObjectGuid const spawnerGuid : _spawners)
- if (Creature* spawner = ObjectAccessor::GetCreature(*me, spawnerGuid))
- spawner->AI()->DoAction(ACTION_DESPAWN_ALL_SPAWNS);
+ void EnterEvadeModeIfNeeded()
+ {
+ Map::PlayerList const& players = me->GetMap()->GetPlayers();
+ for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i)
+ if (Player* player = i->GetSource())
+ if (player->IsAlive() && !player->IsGameMaster() && CheckBoundary(player))
+ return;
- events.Reset();
- summons.DespawnEntry(NPC_ASHTONGUE_CHANNELER);
- instance->SetBossState(DATA_SHADE_OF_AKAMA, DONE);
- }
+ EnterEvadeMode(EVADE_REASON_NO_HOSTILES);
+ }
- void EnterEvadeModeIfNeeded()
- {
- Map::PlayerList const& players = me->GetMap()->GetPlayers();
- for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i)
- if (Player* player = i->GetSource())
- if (player->IsAlive() && !player->IsGameMaster() && CheckBoundary(player))
- return;
+ void UpdateAI(uint32 diff) override
+ {
+ events.Update(diff);
- EnterEvadeMode(EVADE_REASON_NO_HOSTILES);
- }
+ if (!UpdateVictim())
+ return;
- void UpdateAI(uint32 diff) override
+ while (uint32 eventId = events.ExecuteEvent())
{
- events.Update(diff);
-
- if (!UpdateVictim())
- return;
-
- while (uint32 eventId = events.ExecuteEvent())
+ switch (eventId)
{
- switch (eventId)
+ case EVENT_INITIALIZE_SPAWNERS:
{
- case EVENT_INITIALIZE_SPAWNERS:
- {
- std::list<Creature*> SpawnerList;
- me->GetCreatureListWithEntryInGrid(SpawnerList, NPC_CREATURE_SPAWNER_AKAMA);
- for (Creature* spawner : SpawnerList)
- _spawners.push_back(spawner->GetGUID());
+ std::list<Creature*> SpawnerList;
+ me->GetCreatureListWithEntryInGrid(SpawnerList, NPC_CREATURE_SPAWNER_AKAMA);
+ for (Creature* spawner : SpawnerList)
+ _spawners.push_back(spawner->GetGUID());
- break;
- }
- case EVENT_START_CHANNELERS_AND_SPAWNERS:
- {
- for (ObjectGuid const summonGuid : summons)
- if (Creature* channeler = ObjectAccessor::GetCreature(*me, summonGuid))
- channeler->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ break;
+ }
+ case EVENT_START_CHANNELERS_AND_SPAWNERS:
+ {
+ for (ObjectGuid const summonGuid : summons)
+ if (Creature* channeler = ObjectAccessor::GetCreature(*me, summonGuid))
+ channeler->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- for (ObjectGuid const spawnerGuid : _spawners)
- if (Creature* spawner = ObjectAccessor::GetCreature(*me, spawnerGuid))
- spawner->AI()->DoAction(ACTION_START_SPAWNING);
+ for (ObjectGuid const spawnerGuid : _spawners)
+ if (Creature* spawner = ObjectAccessor::GetCreature(*me, spawnerGuid))
+ spawner->AI()->DoAction(ACTION_START_SPAWNING);
- break;
- }
- case EVENT_ADD_THREAT:
- DoCast(SPELL_THREAT);
- events.Repeat(Seconds(3) + Milliseconds(500));
- break;
- case EVENT_EVADE_CHECK:
- EnterEvadeModeIfNeeded();
- events.Repeat(Seconds(10));
- break;
- default:
- break;
+ break;
}
+ case EVENT_ADD_THREAT:
+ DoCast(SPELL_THREAT);
+ events.Repeat(Seconds(3) + Milliseconds(500));
+ break;
+ case EVENT_EVADE_CHECK:
+ EnterEvadeModeIfNeeded();
+ events.Repeat(Seconds(10));
+ break;
+ default:
+ break;
}
-
- DoMeleeAttackIfReady();
}
- private:
- GuidVector _spawners;
- bool _isInPhaseOne;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<boss_shade_of_akamaAI>(creature);
+ DoMeleeAttackIfReady();
}
+
+private:
+ GuidVector _spawners;
+ bool _isInPhaseOne;
};
-class npc_akama_shade : public CreatureScript
+struct npc_akama_shade : public ScriptedAI
{
-public:
- npc_akama_shade() : CreatureScript("npc_akama_shade") { }
-
- struct npc_akamaAI : public ScriptedAI
+ npc_akama_shade(Creature* creature) : ScriptedAI(creature), _summons(me)
{
- npc_akamaAI(Creature* creature) : ScriptedAI(creature), _summons(me)
- {
- Initialize();
- _instance = creature->GetInstanceScript();
- }
+ Initialize();
+ _instance = creature->GetInstanceScript();
+ }
- void Initialize()
- {
- _isInCombat = false;
- _hasYelledOnce = false;
- _chosen.Clear();
- _summons.DespawnAll();
- _events.Reset();
- }
+ void Initialize()
+ {
+ _isInCombat = false;
+ _hasYelledOnce = false;
+ _chosen.Clear();
+ _summons.DespawnAll();
+ _events.Reset();
+ }
- void Reset() override
- {
- Initialize();
- me->SetFaction(FACTION_ASHTONGUE_DEATHSWORN);
- DoCastSelf(SPELL_STEALTH);
+ void Reset() override
+ {
+ Initialize();
+ me->SetFaction(FACTION_ASHTONGUE_DEATHSWORN);
+ DoCastSelf(SPELL_STEALTH);
- if (_instance->GetBossState(DATA_SHADE_OF_AKAMA) != DONE)
- me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
- }
+ if (_instance->GetBossState(DATA_SHADE_OF_AKAMA) != DONE)
+ me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ }
- void JustSummoned(Creature* summon) override
- {
- _summons.Summon(summon);
- }
+ void JustSummoned(Creature* summon) override
+ {
+ _summons.Summon(summon);
+ }
- void EnterEvadeMode(EvadeReason /*why*/) override { }
+ void EnterEvadeMode(EvadeReason /*why*/) override { }
- void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
+ {
+ if (spell->Id == SPELL_THREAT && !_isInCombat)
{
- if (spell->Id == SPELL_THREAT && !_isInCombat)
+ _isInCombat = true;
+ me->SetWalk(false);
+ me->RemoveAurasDueToSpell(SPELL_AKAMA_SOUL_CHANNEL);
+ if (Creature* shade = _instance->GetCreature(DATA_SHADE_OF_AKAMA))
{
- _isInCombat = true;
- me->SetWalk(false);
- me->RemoveAurasDueToSpell(SPELL_AKAMA_SOUL_CHANNEL);
- if (Creature* shade = _instance->GetCreature(DATA_SHADE_OF_AKAMA))
- {
- shade->RemoveAurasDueToSpell(SPELL_AKAMA_SOUL_CHANNEL);
- AttackStart(shade);
- _events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, Seconds(2));
- _events.ScheduleEvent(EVENT_DESTRUCTIVE_POISON, Seconds(5));
- }
+ shade->RemoveAurasDueToSpell(SPELL_AKAMA_SOUL_CHANNEL);
+ AttackStart(shade);
+ _events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, Seconds(2));
+ _events.ScheduleEvent(EVENT_DESTRUCTIVE_POISON, Seconds(5));
}
}
+ }
- void DamageTaken(Unit* /*who*/, uint32& /*damage*/) override
+ void DamageTaken(Unit* /*who*/, uint32& /*damage*/) override
+ {
+ if (me->HealthBelowPct(20) && !_hasYelledOnce)
{
- if (me->HealthBelowPct(20) && !_hasYelledOnce)
- {
- _hasYelledOnce = true;
- Talk(SAY_LOW_HEALTH);
- }
+ _hasYelledOnce = true;
+ Talk(SAY_LOW_HEALTH);
}
+ }
- void DoAction(int32 actionId) override
+ void DoAction(int32 actionId) override
+ {
+ if (actionId == ACTION_SHADE_OF_AKAMA_DEAD)
{
- if (actionId == ACTION_SHADE_OF_AKAMA_DEAD)
- {
- _isInCombat = false;
- me->CombatStop(true);
- me->SetFaction(FACTION_ASHTONGUE_DEATHSWORN);
- me->SetWalk(true);
- _events.Reset();
- me->GetMotionMaster()->MovePoint(AKAMA_INTRO_WAYPOINT, AkamaWP[1]);
- }
+ _isInCombat = false;
+ me->CombatStop(true);
+ me->SetFaction(FACTION_ASHTONGUE_DEATHSWORN);
+ me->SetWalk(true);
+ _events.Reset();
+ me->GetMotionMaster()->MovePoint(AKAMA_INTRO_WAYPOINT, AkamaWP[1]);
}
+ }
- void MovementInform(uint32 motionType, uint32 pointId) override
- {
- if (motionType != POINT_MOTION_TYPE)
- return;
+ void MovementInform(uint32 motionType, uint32 pointId) override
+ {
+ if (motionType != POINT_MOTION_TYPE)
+ return;
- if (pointId == AKAMA_CHANNEL_WAYPOINT)
- _events.ScheduleEvent(EVENT_SHADE_CHANNEL, Seconds(1));
+ if (pointId == AKAMA_CHANNEL_WAYPOINT)
+ _events.ScheduleEvent(EVENT_SHADE_CHANNEL, Seconds(1));
- else if (pointId == AKAMA_INTRO_WAYPOINT)
- {
- me->SetWalk(false);
- _events.ScheduleEvent(EVENT_START_SOUL_RETRIEVE, Seconds(1));
- }
+ else if (pointId == AKAMA_INTRO_WAYPOINT)
+ {
+ me->SetWalk(false);
+ _events.ScheduleEvent(EVENT_START_SOUL_RETRIEVE, Seconds(1));
}
+ }
- void SummonBrokens()
+ void SummonBrokens()
+ {
+ for (uint8 i = 0; i < 18; i++)
{
- for (uint8 i = 0; i < 18; i++)
+ if (TempSummon* summoned = me->SummonCreature(NPC_ASHTONGUE_BROKEN, BrokenPos[i]))
{
- if (TempSummon* summoned = me->SummonCreature(NPC_ASHTONGUE_BROKEN, BrokenPos[i]))
- {
- summoned->SetWalk(true);
- summoned->GetMotionMaster()->MovePoint(0, BrokenWP[i]);
- if (i == 9) //On Sniffs, npc that Yell "Special" is the tenth to be created
- _chosen = summoned->GetGUID();
- }
+ summoned->SetWalk(true);
+ summoned->GetMotionMaster()->MovePoint(0, BrokenWP[i]);
+ if (i == 9) //On Sniffs, npc that Yell "Special" is the tenth to be created
+ _chosen = summoned->GetGUID();
}
}
+ }
- void UpdateAI(uint32 diff) override
- {
- _events.Update(diff);
-
- while (uint32 eventId = _events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_SHADE_START:
- _instance->SetBossState(DATA_SHADE_OF_AKAMA, IN_PROGRESS);
- me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
- me->RemoveAurasDueToSpell(SPELL_STEALTH);
- me->SetWalk(true);
- me->GetMotionMaster()->MovePoint(AKAMA_CHANNEL_WAYPOINT, AkamaWP[0], false);
- break;
- case EVENT_SHADE_CHANNEL:
- me->SetFacingTo(FACE_THE_PLATFORM);
- DoCastSelf(SPELL_AKAMA_SOUL_CHANNEL);
- me->SetFaction(FACTION_MONSTER_SPAR_BUDDY);
- _events.ScheduleEvent(EVENT_FIXATE, Seconds(5));
- break;
- case EVENT_FIXATE:
- DoCast(SPELL_FIXATE);
- break;
- case EVENT_CHAIN_LIGHTNING:
- DoCastVictim(SPELL_CHAIN_LIGHTNING);
- _events.Repeat(Seconds(8), Seconds(15));
- break;
- case EVENT_DESTRUCTIVE_POISON:
- DoCastSelf(SPELL_DESTRUCTIVE_POISON);
- _events.Repeat(Seconds(3), Seconds(7));
- break;
- case EVENT_START_SOUL_RETRIEVE:
- me->SetFacingTo(FACE_THE_DOOR);
- DoCast(SPELL_AKAMA_SOUL_RETRIEVE);
- _events.ScheduleEvent(EVENT_START_BROKEN_FREE, Seconds(15));
- break;
- case EVENT_START_BROKEN_FREE:
- me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR);
- Talk(SAY_BROKEN_FREE_0);
- SummonBrokens();
- _events.ScheduleEvent(EVENT_BROKEN_FREE_1, Seconds(10));
- break;
- case EVENT_BROKEN_FREE_1:
- Talk(SAY_BROKEN_FREE_1);
- _events.ScheduleEvent(EVENT_BROKEN_FREE_2, Seconds(12));
- break;
- case EVENT_BROKEN_FREE_2:
- Talk(SAY_BROKEN_FREE_2);
- _events.ScheduleEvent(EVENT_BROKEN_FREE_3, Seconds(15));
- break;
- case EVENT_BROKEN_FREE_3:
- if (Creature* special = ObjectAccessor::GetCreature(*me, _chosen))
- special->AI()->Talk(SAY_BROKEN_SPECIAL);
-
- _summons.DoAction(ACTION_BROKEN_EMOTE, _pred);
- _events.ScheduleEvent(EVENT_BROKEN_FREE_4, Seconds(5));
- break;
- case EVENT_BROKEN_FREE_4:
- _summons.DoAction(ACTION_BROKEN_HAIL, _pred);
- break;
- default:
- break;
- }
- }
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
- if (me->GetFaction() == FACTION_MONSTER_SPAR_BUDDY)
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
{
- if (!UpdateVictim())
- return;
+ case EVENT_SHADE_START:
+ _instance->SetBossState(DATA_SHADE_OF_AKAMA, IN_PROGRESS);
+ me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ me->RemoveAurasDueToSpell(SPELL_STEALTH);
+ me->SetWalk(true);
+ me->GetMotionMaster()->MovePoint(AKAMA_CHANNEL_WAYPOINT, AkamaWP[0], false);
+ break;
+ case EVENT_SHADE_CHANNEL:
+ me->SetFacingTo(FACE_THE_PLATFORM);
+ DoCastSelf(SPELL_AKAMA_SOUL_CHANNEL);
+ me->SetFaction(FACTION_MONSTER_SPAR_BUDDY);
+ _events.ScheduleEvent(EVENT_FIXATE, Seconds(5));
+ break;
+ case EVENT_FIXATE:
+ DoCast(SPELL_FIXATE);
+ break;
+ case EVENT_CHAIN_LIGHTNING:
+ DoCastVictim(SPELL_CHAIN_LIGHTNING);
+ _events.Repeat(Seconds(8), Seconds(15));
+ break;
+ case EVENT_DESTRUCTIVE_POISON:
+ DoCastSelf(SPELL_DESTRUCTIVE_POISON);
+ _events.Repeat(Seconds(3), Seconds(7));
+ break;
+ case EVENT_START_SOUL_RETRIEVE:
+ me->SetFacingTo(FACE_THE_DOOR);
+ DoCast(SPELL_AKAMA_SOUL_RETRIEVE);
+ _events.ScheduleEvent(EVENT_START_BROKEN_FREE, Seconds(15));
+ break;
+ case EVENT_START_BROKEN_FREE:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR);
+ Talk(SAY_BROKEN_FREE_0);
+ SummonBrokens();
+ _events.ScheduleEvent(EVENT_BROKEN_FREE_1, Seconds(10));
+ break;
+ case EVENT_BROKEN_FREE_1:
+ Talk(SAY_BROKEN_FREE_1);
+ _events.ScheduleEvent(EVENT_BROKEN_FREE_2, Seconds(12));
+ break;
+ case EVENT_BROKEN_FREE_2:
+ Talk(SAY_BROKEN_FREE_2);
+ _events.ScheduleEvent(EVENT_BROKEN_FREE_3, Seconds(15));
+ break;
+ case EVENT_BROKEN_FREE_3:
+ if (Creature* special = ObjectAccessor::GetCreature(*me, _chosen))
+ special->AI()->Talk(SAY_BROKEN_SPECIAL);
- DoMeleeAttackIfReady();
+ _summons.DoAction(ACTION_BROKEN_EMOTE, _pred);
+ _events.ScheduleEvent(EVENT_BROKEN_FREE_4, Seconds(5));
+ break;
+ case EVENT_BROKEN_FREE_4:
+ _summons.DoAction(ACTION_BROKEN_HAIL, _pred);
+ break;
+ default:
+ break;
}
}
- void JustDied(Unit* /*killer*/) override
+ if (me->GetFaction() == FACTION_MONSTER_SPAR_BUDDY)
{
- _summons.DespawnAll();
- Talk(SAY_DEAD);
- if (Creature* shade = _instance->GetCreature(DATA_SHADE_OF_AKAMA))
- if (shade->IsAlive())
- shade->AI()->EnterEvadeMode(EVADE_REASON_OTHER);
- }
+ if (!UpdateVictim())
+ return;
- bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
- {
- if (gossipListId == 0)
- {
- CloseGossipMenuFor(player);
- _events.ScheduleEvent(EVENT_SHADE_START, Milliseconds(500));
- }
- return false;
+ DoMeleeAttackIfReady();
}
+ }
- private:
- InstanceScript* _instance;
- EventMap _events;
- SummonList _summons;
- DummyEntryCheckPredicate _pred;
- ObjectGuid _chosen; //Creature that should yell the speech special.
- bool _isInCombat;
- bool _hasYelledOnce;
- };
+ void JustDied(Unit* /*killer*/) override
+ {
+ _summons.DespawnAll();
+ Talk(SAY_DEAD);
+ if (Creature* shade = _instance->GetCreature(DATA_SHADE_OF_AKAMA))
+ if (shade->IsAlive())
+ shade->AI()->EnterEvadeMode(EVADE_REASON_OTHER);
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
{
- return GetBlackTempleAI<npc_akamaAI>(creature);
+ if (gossipListId == 0)
+ {
+ CloseGossipMenuFor(player);
+ _events.ScheduleEvent(EVENT_SHADE_START, Milliseconds(500));
+ }
+ return false;
}
+
+private:
+ InstanceScript* _instance;
+ EventMap _events;
+ SummonList _summons;
+ DummyEntryCheckPredicate _pred;
+ ObjectGuid _chosen; //Creature that should yell the speech special.
+ bool _isInCombat;
+ bool _hasYelledOnce;
};
-class npc_ashtongue_channeler : public CreatureScript
+struct npc_ashtongue_channeler : public PassiveAI
{
-public:
- npc_ashtongue_channeler() : CreatureScript("npc_ashtongue_channeler") { }
-
- struct npc_ashtongue_channelerAI : public PassiveAI
+ npc_ashtongue_channeler(Creature* creature) : PassiveAI(creature)
{
- npc_ashtongue_channelerAI(Creature* creature) : PassiveAI(creature)
- {
- _instance = creature->GetInstanceScript();
- }
+ _instance = creature->GetInstanceScript();
+ }
- void Reset() override
+ void Reset() override
+ {
+ _scheduler.Schedule(Seconds(2), [this](TaskContext channel)
{
- _scheduler.Schedule(Seconds(2), [this](TaskContext channel)
+ if (Creature* shade = _instance->GetCreature(DATA_SHADE_OF_AKAMA))
{
- if (Creature* shade = _instance->GetCreature(DATA_SHADE_OF_AKAMA))
- {
- if (shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
- DoCastSelf(SPELL_SHADE_SOUL_CHANNEL);
-
- else
- me->DespawnOrUnsummon(Seconds(3));
- }
-
- channel.Repeat(Seconds(2));
- });
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- }
+ if (shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
+ DoCastSelf(SPELL_SHADE_SOUL_CHANNEL);
- void UpdateAI(uint32 diff) override
- {
- _scheduler.Update(diff);
- }
+ else
+ me->DespawnOrUnsummon(Seconds(3));
+ }
- private:
- InstanceScript* _instance;
- TaskScheduler _scheduler;
- };
+ channel.Repeat(Seconds(2));
+ });
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void UpdateAI(uint32 diff) override
{
- return GetBlackTempleAI<npc_ashtongue_channelerAI>(creature);
+ _scheduler.Update(diff);
}
+
+private:
+ InstanceScript* _instance;
+ TaskScheduler _scheduler;
};
-class npc_creature_generator_akama : public CreatureScript
+struct npc_creature_generator_akama : public ScriptedAI
{
-public:
- npc_creature_generator_akama() : CreatureScript("npc_creature_generator_akama") { }
+ npc_creature_generator_akama(Creature* creature) : ScriptedAI(creature), _summons(me)
+ {
+ Initialize();
+ }
- struct npc_creature_generator_akamaAI : public ScriptedAI
+ void Initialize()
{
- npc_creature_generator_akamaAI(Creature* creature) : ScriptedAI(creature), _summons(me)
- {
- Initialize();
- }
+ _leftSide = false;
+ _events.Reset();
+ _summons.DespawnAll();
+ }
- void Initialize()
- {
- _leftSide = false;
- _events.Reset();
- _summons.DespawnAll();
- }
+ void Reset() override
+ {
+ Initialize();
- void Reset() override
- {
- Initialize();
+ if (me->GetPositionY() < MIDDLE_OF_ROOM)
+ _leftSide = true;
+ }
- if (me->GetPositionY() < MIDDLE_OF_ROOM)
- _leftSide = true;
- }
+ void JustSummoned(Creature* summon) override
+ {
+ _summons.Summon(summon);
+ }
- void JustSummoned(Creature* summon) override
+ void DoAction(int32 actionId) override
+ {
+ switch (actionId)
{
- _summons.Summon(summon);
+ case ACTION_START_SPAWNING:
+ if (_leftSide)
+ {
+ _events.ScheduleEvent(EVENT_SPAWN_WAVE_B, Milliseconds(100));
+ _events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_SORCERER, Seconds(2), Seconds(5));
+ }
+ else
+ {
+ _events.ScheduleEvent(EVENT_SPAWN_WAVE_B, Seconds(10));
+ _events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_DEFENDER, Seconds(2), Seconds(5));
+ }
+ break;
+ case ACTION_STOP_SPAWNING:
+ _events.Reset();
+ break;
+ case ACTION_DESPAWN_ALL_SPAWNS:
+ _events.Reset();
+ _summons.DespawnAll();
+ break;
+ default:
+ break;
}
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
- void DoAction(int32 actionId) override
+ while (uint32 eventId = _events.ExecuteEvent())
{
- switch (actionId)
+ switch (eventId)
{
- case ACTION_START_SPAWNING:
- if (_leftSide)
- {
- _events.ScheduleEvent(EVENT_SPAWN_WAVE_B, Milliseconds(100));
- _events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_SORCERER, Seconds(2), Seconds(5));
- }
- else
- {
- _events.ScheduleEvent(EVENT_SPAWN_WAVE_B, Seconds(10));
- _events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_DEFENDER, Seconds(2), Seconds(5));
- }
+ case EVENT_SPAWN_WAVE_B:
+ DoCastSelf(SPELL_ASHTONGUE_WAVE_B);
+ _events.Repeat(Seconds(50), Seconds(60));
break;
- case ACTION_STOP_SPAWNING:
- _events.Reset();
+ case EVENT_SUMMON_ASHTONGUE_SORCERER: // left
+ DoCastSelf(SPELL_SUMMON_ASHTONGUE_SORCERER);
+ _events.Repeat(Seconds(30), Seconds(35));
break;
- case ACTION_DESPAWN_ALL_SPAWNS:
- _events.Reset();
- _summons.DespawnAll();
+ case EVENT_SUMMON_ASHTONGUE_DEFENDER: // right
+ DoCastSelf(SPELL_SUMMON_ASHTONGUE_DEFENDER);
+ _events.Repeat(Seconds(30), Seconds(40));
break;
default:
break;
}
}
+ }
- void UpdateAI(uint32 diff) override
- {
- _events.Update(diff);
-
- while (uint32 eventId = _events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_SPAWN_WAVE_B:
- DoCastSelf(SPELL_ASHTONGUE_WAVE_B);
- _events.Repeat(Seconds(50), Seconds(60));
- break;
- case EVENT_SUMMON_ASHTONGUE_SORCERER: // left
- DoCastSelf(SPELL_SUMMON_ASHTONGUE_SORCERER);
- _events.Repeat(Seconds(30), Seconds(35));
- break;
- case EVENT_SUMMON_ASHTONGUE_DEFENDER: // right
- DoCastSelf(SPELL_SUMMON_ASHTONGUE_DEFENDER);
- _events.Repeat(Seconds(30), Seconds(40));
- break;
- default:
- break;
- }
- }
- }
-
- private:
- EventMap _events;
- SummonList _summons;
- bool _leftSide;
- };
+private:
+ EventMap _events;
+ SummonList _summons;
+ bool _leftSide;
+};
- CreatureAI* GetAI(Creature* creature) const override
+struct npc_ashtongue_sorcerer : public ScriptedAI
+{
+ npc_ashtongue_sorcerer(Creature* creature) : ScriptedAI(creature)
{
- return GetBlackTempleAI<npc_creature_generator_akamaAI>(creature);
+ Initialize();
+ _instance = creature->GetInstanceScript();
}
-};
-class npc_ashtongue_sorcerer : public CreatureScript
-{
-public:
- npc_ashtongue_sorcerer() : CreatureScript("npc_ashtongue_sorcerer") { }
+ void Initialize()
+ {
+ _switchToCombat = false;
+ _inBanish = false;
+ }
- struct npc_ashtongue_sorcererAI : public ScriptedAI
+ void Reset() override
{
- npc_ashtongue_sorcererAI(Creature* creature) : ScriptedAI(creature)
+ if (Creature* shade = _instance->GetCreature(DATA_SHADE_OF_AKAMA))
{
- Initialize();
- _instance = creature->GetInstanceScript();
- }
+ if (shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
+ me->GetMotionMaster()->MovePoint(0, shade->GetPosition());
- void Initialize()
- {
- _switchToCombat = false;
- _inBanish = false;
+ else if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
+ AttackStart(akama);
}
+ Initialize();
+ }
- void Reset() override
- {
- if (Creature* shade = _instance->GetCreature(DATA_SHADE_OF_AKAMA))
- {
- if (shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
- me->GetMotionMaster()->MovePoint(0, shade->GetPosition());
+ void JustDied(Unit* /*killer*/) override
+ {
+ me->DespawnOrUnsummon(Seconds(5));
+ }
- else if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
- AttackStart(akama);
- }
- Initialize();
- }
+ void EnterEvadeMode(EvadeReason /*why*/) override { }
+ void EnterCombat(Unit* /*who*/) override { }
- void JustDied(Unit* /*killer*/) override
- {
- me->DespawnOrUnsummon(Seconds(5));
- }
+ void AttackStart(Unit* who) override
+ {
+ if (!_switchToCombat)
+ return;
- void EnterEvadeMode(EvadeReason /*why*/) override { }
- void EnterCombat(Unit* /*who*/) override { }
+ ScriptedAI::AttackStart(who);
+ }
- void AttackStart(Unit* who) override
+ void MoveInLineOfSight(Unit* who) override
+ {
+ if (!_inBanish && who->GetGUID() == _instance->GetGuidData(DATA_SHADE_OF_AKAMA) && me->IsWithinDist(who, 20.0f, false))
{
- if (!_switchToCombat)
- return;
+ _inBanish = true;
+ me->StopMoving();
+ me->GetMotionMaster()->Clear(false);
+ me->GetMotionMaster()->MovePoint(1, me->GetPositionX() + frand(-8.0f, 8.0f), me->GetPositionY() + frand(-8.0f, 8.0f), me->GetPositionZ());
- ScriptedAI::AttackStart(who);
- }
-
- void MoveInLineOfSight(Unit* who) override
- {
- if (!_inBanish && who->GetGUID() == _instance->GetGuidData(DATA_SHADE_OF_AKAMA) && me->IsWithinDist(who, 20.0f, false))
+ _scheduler.Schedule(Seconds(1) + Milliseconds(500), [this](TaskContext sorcer_channel)
{
- _inBanish = true;
- me->StopMoving();
- me->GetMotionMaster()->Clear(false);
- me->GetMotionMaster()->MovePoint(1, me->GetPositionX() + frand(-8.0f, 8.0f), me->GetPositionY() + frand(-8.0f, 8.0f), me->GetPositionZ());
-
- _scheduler.Schedule(Seconds(1) + Milliseconds(500), [this](TaskContext sorcer_channel)
+ if (Creature* shade = _instance->GetCreature(DATA_SHADE_OF_AKAMA))
{
- if (Creature* shade = _instance->GetCreature(DATA_SHADE_OF_AKAMA))
+ if (shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
+ {
+ me->SetFacingToObject(shade);
+ DoCastSelf(SPELL_SHADE_SOUL_CHANNEL);
+ sorcer_channel.Repeat(Seconds(2));
+ }
+ else
{
- if (shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
- {
- me->SetFacingToObject(shade);
- DoCastSelf(SPELL_SHADE_SOUL_CHANNEL);
- sorcer_channel.Repeat(Seconds(2));
- }
- else
- {
- me->InterruptSpell(CURRENT_CHANNELED_SPELL);
- _switchToCombat = true;
- if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
- AttackStart(akama);
- }
+ me->InterruptSpell(CURRENT_CHANNELED_SPELL);
+ _switchToCombat = true;
+ if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
+ AttackStart(akama);
}
- });
- }
+ }
+ });
}
+ }
- void UpdateAI(uint32 diff) override
- {
- _scheduler.Update(diff);
+ void UpdateAI(uint32 diff) override
+ {
+ _scheduler.Update(diff);
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- if (!UpdateVictim())
- return;
+ if (!UpdateVictim())
+ return;
- DoMeleeAttackIfReady();
- }
+ DoMeleeAttackIfReady();
+ }
- private:
- InstanceScript* _instance;
- TaskScheduler _scheduler;
- bool _switchToCombat;
- bool _inBanish;
- };
+private:
+ InstanceScript* _instance;
+ TaskScheduler _scheduler;
+ bool _switchToCombat;
+ bool _inBanish;
+};
- CreatureAI* GetAI(Creature* creature) const override
+struct npc_ashtongue_defender : public ScriptedAI
+{
+ npc_ashtongue_defender(Creature* creature) : ScriptedAI(creature)
{
- return GetBlackTempleAI<npc_ashtongue_sorcererAI>(creature);
+ _instance = creature->GetInstanceScript();
}
-};
-class npc_ashtongue_defender : public CreatureScript
-{
-public:
- npc_ashtongue_defender() : CreatureScript("npc_ashtongue_defender") { }
+ void Reset() override
+ {
+ if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
+ AttackStart(akama);
+ }
- struct npc_ashtongue_defenderAI : public ScriptedAI
+ void JustDied(Unit* /*killer*/) override
{
- npc_ashtongue_defenderAI(Creature* creature) : ScriptedAI(creature)
- {
- _instance = creature->GetInstanceScript();
- }
+ me->DespawnOrUnsummon(Seconds(5));
+ }
- void Reset() override
- {
- if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
- AttackStart(akama);
- }
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_HEROIC_STRIKE, Seconds(5));
+ _events.ScheduleEvent(EVENT_SHIELD_BASH, Seconds(10), Seconds(16));
+ _events.ScheduleEvent(EVENT_DEBILITATING_STRIKE, Seconds(10), Seconds(16));
+ _events.ScheduleEvent(EVENT_WINDFURY, Seconds(8), Seconds(12));
+ }
- void JustDied(Unit* /*killer*/) override
- {
- me->DespawnOrUnsummon(Seconds(5));
- }
- void EnterCombat(Unit* /*who*/) override
- {
- _events.ScheduleEvent(EVENT_HEROIC_STRIKE, Seconds(5));
- _events.ScheduleEvent(EVENT_SHIELD_BASH, Seconds(10), Seconds(16));
- _events.ScheduleEvent(EVENT_DEBILITATING_STRIKE, Seconds(10), Seconds(16));
- _events.ScheduleEvent(EVENT_WINDFURY, Seconds(8), Seconds(12));
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+ _events.Update(diff);
- void UpdateAI(uint32 diff) override
+ while (uint32 eventId = _events.ExecuteEvent())
{
- if (!UpdateVictim())
- return;
-
- _events.Update(diff);
-
- while (uint32 eventId = _events.ExecuteEvent())
+ switch (eventId)
{
- switch (eventId)
- {
- case EVENT_DEBILITATING_STRIKE:
- DoCastVictim(SPELL_DEBILITATING_STRIKE);
- _events.Repeat(Seconds(20), Seconds(25));
- break;
- case EVENT_HEROIC_STRIKE:
- DoCastSelf(SPELL_HEROIC_STRIKE);
- _events.Repeat(Seconds(5), Seconds(15));
- break;
- case EVENT_SHIELD_BASH:
- DoCastVictim(SPELL_SHIELD_BASH);
- _events.Repeat(Seconds(10), Seconds(20));
- break;
- case EVENT_WINDFURY:
- DoCastVictim(SPELL_WINDFURY);
- _events.Repeat(Seconds(6), Seconds(8));
- break;
- default:
- break;
- }
+ case EVENT_DEBILITATING_STRIKE:
+ DoCastVictim(SPELL_DEBILITATING_STRIKE);
+ _events.Repeat(Seconds(20), Seconds(25));
+ break;
+ case EVENT_HEROIC_STRIKE:
+ DoCastSelf(SPELL_HEROIC_STRIKE);
+ _events.Repeat(Seconds(5), Seconds(15));
+ break;
+ case EVENT_SHIELD_BASH:
+ DoCastVictim(SPELL_SHIELD_BASH);
+ _events.Repeat(Seconds(10), Seconds(20));
+ break;
+ case EVENT_WINDFURY:
+ DoCastVictim(SPELL_WINDFURY);
+ _events.Repeat(Seconds(6), Seconds(8));
+ break;
+ default:
+ break;
}
-
- DoMeleeAttackIfReady();
}
- private:
- InstanceScript* _instance;
- EventMap _events;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<npc_ashtongue_defenderAI>(creature);
+ DoMeleeAttackIfReady();
}
+
+private:
+ InstanceScript* _instance;
+ EventMap _events;
};
-class npc_ashtongue_rogue : public CreatureScript
+struct npc_ashtongue_rogue : public ScriptedAI
{
-public:
- npc_ashtongue_rogue() : CreatureScript("npc_ashtongue_rogue") { }
-
- struct npc_ashtongue_rogueAI : public ScriptedAI
+ npc_ashtongue_rogue(Creature* creature) : ScriptedAI(creature)
{
- npc_ashtongue_rogueAI(Creature* creature) : ScriptedAI(creature)
- {
- _instance = creature->GetInstanceScript();
- }
+ _instance = creature->GetInstanceScript();
+ }
- void Reset() override
- {
- if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
- AttackStart(akama);
- }
+ void Reset() override
+ {
+ if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
+ AttackStart(akama);
+ }
- void JustDied(Unit* /*killer*/) override
- {
- me->DespawnOrUnsummon(Seconds(5));
- }
+ void JustDied(Unit* /*killer*/) override
+ {
+ me->DespawnOrUnsummon(Seconds(5));
+ }
- void EnterCombat(Unit* /*who*/) override
- {
- _events.ScheduleEvent(EVENT_DEBILITATING_POISON, Milliseconds(500), Seconds(2));
- _events.ScheduleEvent(EVENT_EVISCERATE, Seconds(2), Seconds(5));
- }
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_DEBILITATING_POISON, Milliseconds(500), Seconds(2));
+ _events.ScheduleEvent(EVENT_EVISCERATE, Seconds(2), Seconds(5));
+ }
- void EnterEvadeMode(EvadeReason /*why*/) override { }
+ void EnterEvadeMode(EvadeReason /*why*/) override { }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- _events.Update(diff);
+ _events.Update(diff);
- while (uint32 eventId = _events.ExecuteEvent())
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
{
- switch (eventId)
- {
- case EVENT_DEBILITATING_POISON:
- DoCastVictim(SPELL_DEBILITATING_POISON);
- _events.Repeat(Seconds(15), Seconds(20));
- break;
- case EVENT_EVISCERATE:
- DoCastVictim(SPELL_EVISCERATE);
- _events.Repeat(Seconds(12), Seconds(20));
- break;
- default:
- break;
- }
+ case EVENT_DEBILITATING_POISON:
+ DoCastVictim(SPELL_DEBILITATING_POISON);
+ _events.Repeat(Seconds(15), Seconds(20));
+ break;
+ case EVENT_EVISCERATE:
+ DoCastVictim(SPELL_EVISCERATE);
+ _events.Repeat(Seconds(12), Seconds(20));
+ break;
+ default:
+ break;
}
-
- DoMeleeAttackIfReady();
}
- private:
- InstanceScript* _instance;
- EventMap _events;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<npc_ashtongue_rogueAI>(creature);
+ DoMeleeAttackIfReady();
}
+
+private:
+ InstanceScript* _instance;
+ EventMap _events;
};
-class npc_ashtongue_elementalist : public CreatureScript
+struct npc_ashtongue_elementalist : public ScriptedAI
{
-public:
- npc_ashtongue_elementalist() : CreatureScript("npc_ashtongue_elementalist") { }
-
- struct npc_ashtongue_elementalistAI : public ScriptedAI
+ npc_ashtongue_elementalist(Creature* creature) : ScriptedAI(creature)
{
- npc_ashtongue_elementalistAI(Creature* creature) : ScriptedAI(creature)
- {
- _instance = creature->GetInstanceScript();
- }
+ _instance = creature->GetInstanceScript();
+ }
- void Reset() override
- {
- if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
- AttackStart(akama);
- }
+ void Reset() override
+ {
+ if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
+ AttackStart(akama);
+ }
- void JustDied(Unit* /*killer*/) override
- {
- me->DespawnOrUnsummon(Seconds(5));
- }
+ void JustDied(Unit* /*killer*/) override
+ {
+ me->DespawnOrUnsummon(Seconds(5));
+ }
- void EnterCombat(Unit* /*who*/) override
- {
- _events.ScheduleEvent(EVENT_RAIN_OF_FIRE, Seconds(18));
- _events.ScheduleEvent(EVENT_LIGHTNING_BOLT, Seconds(6));
- }
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_RAIN_OF_FIRE, Seconds(18));
+ _events.ScheduleEvent(EVENT_LIGHTNING_BOLT, Seconds(6));
+ }
- void EnterEvadeMode(EvadeReason /*why*/) override { }
+ void EnterEvadeMode(EvadeReason /*why*/) override { }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- _events.Update(diff);
+ _events.Update(diff);
- while (uint32 eventId = _events.ExecuteEvent())
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
{
- switch (eventId)
- {
- case EVENT_RAIN_OF_FIRE:
- DoCastVictim(SPELL_RAIN_OF_FIRE);
- _events.Repeat(Seconds(15), Seconds(20));
- break;
- case EVENT_LIGHTNING_BOLT:
- DoCastVictim(SPELL_LIGHTNING_BOLT);
- _events.Repeat(Seconds(8), Seconds(15));
- break;
- default:
- break;
- }
+ case EVENT_RAIN_OF_FIRE:
+ DoCastVictim(SPELL_RAIN_OF_FIRE);
+ _events.Repeat(Seconds(15), Seconds(20));
+ break;
+ case EVENT_LIGHTNING_BOLT:
+ DoCastVictim(SPELL_LIGHTNING_BOLT);
+ _events.Repeat(Seconds(8), Seconds(15));
+ break;
+ default:
+ break;
}
-
- DoMeleeAttackIfReady();
}
- private:
- InstanceScript* _instance;
- EventMap _events;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<npc_ashtongue_elementalistAI>(creature);
+ DoMeleeAttackIfReady();
}
+
+private:
+ InstanceScript* _instance;
+ EventMap _events;
};
-class npc_ashtongue_spiritbinder : public CreatureScript
+struct npc_ashtongue_spiritbinder : public ScriptedAI
{
-public:
- npc_ashtongue_spiritbinder() : CreatureScript("npc_ashtongue_spiritbinder") { }
-
- struct npc_ashtongue_spiritbinderAI : public ScriptedAI
+ npc_ashtongue_spiritbinder(Creature* creature) : ScriptedAI(creature)
{
- npc_ashtongue_spiritbinderAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- _instance = creature->GetInstanceScript();
- }
-
- void Initialize()
- {
- _spiritMend = false;
- _chainHeal = false;
- }
-
- void Reset() override
- {
- Initialize();
-
- if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
- AttackStart(akama);
- }
-
- void JustDied(Unit* /*killer*/) override
- {
- me->DespawnOrUnsummon(Seconds(5));
- }
-
- void EnterCombat(Unit* /*who*/) override
- {
- _events.ScheduleEvent(EVENT_SPIRIT_HEAL, Seconds(5), Seconds(6));
- }
+ Initialize();
+ _instance = creature->GetInstanceScript();
+ }
- void DamageTaken(Unit* /*who*/, uint32& /*damage*/) override
- {
- if (!_spiritMend)
- if (HealthBelowPct(30))
- {
- DoCastSelf(SPELL_SPIRIT_MEND);
- _spiritMend = true;
- _events.ScheduleEvent(EVENT_SPIRIT_MEND_RESET, Seconds(10),Seconds(15));
- }
+ void Initialize()
+ {
+ _spiritMend = false;
+ _chainHeal = false;
+ }
- if (!_chainHeal)
- if (HealthBelowPct(50))
- {
- DoCastSelf(SPELL_CHAIN_HEAL);
- _chainHeal = true;
- _events.ScheduleEvent(EVENT_CHAIN_HEAL_RESET, Seconds(10), Seconds(15));
- }
+ void Reset() override
+ {
+ Initialize();
- }
+ if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
+ AttackStart(akama);
+ }
- void EnterEvadeMode(EvadeReason /*why*/) override { }
+ void JustDied(Unit* /*killer*/) override
+ {
+ me->DespawnOrUnsummon(Seconds(5));
+ }
- void UpdateAI(uint32 diff) override
- {
- _events.Update(diff);
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_SPIRIT_HEAL, Seconds(5), Seconds(6));
+ }
- while (uint32 eventId = _events.ExecuteEvent())
+ void DamageTaken(Unit* /*who*/, uint32& /*damage*/) override
+ {
+ if (!_spiritMend)
+ if (HealthBelowPct(30))
{
- switch (eventId)
- {
- case EVENT_SPIRIT_HEAL:
- DoCastSelf(SPELL_SPIRITBINDER_SPIRIT_HEAL);
- _events.Repeat(Seconds(13), Seconds(16));
- break;
- case EVENT_SPIRIT_MEND_RESET:
- _spiritMend = false;
- break;
- case EVENT_CHAIN_HEAL_RESET:
- _chainHeal = false;
- break;
- default:
- break;
- }
+ DoCastSelf(SPELL_SPIRIT_MEND);
+ _spiritMend = true;
+ _events.ScheduleEvent(EVENT_SPIRIT_MEND_RESET, Seconds(10), Seconds(15));
}
- if (!UpdateVictim())
- return;
-
- DoMeleeAttackIfReady();
- }
-
- private:
- InstanceScript* _instance;
- EventMap _events;
- bool _spiritMend;
- bool _chainHeal;
- };
+ if (!_chainHeal)
+ if (HealthBelowPct(50))
+ {
+ DoCastSelf(SPELL_CHAIN_HEAL);
+ _chainHeal = true;
+ _events.ScheduleEvent(EVENT_CHAIN_HEAL_RESET, Seconds(10), Seconds(15));
+ }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<npc_ashtongue_spiritbinderAI>(creature);
}
-};
-class npc_ashtongue_broken : public CreatureScript
-{
-public:
- npc_ashtongue_broken() : CreatureScript("npc_ashtongue_broken") { }
+ void EnterEvadeMode(EvadeReason /*why*/) override { }
- struct npc_ashtongue_brokenAI : public ScriptedAI
+ void UpdateAI(uint32 diff) override
{
- npc_ashtongue_brokenAI(Creature* creature) : ScriptedAI(creature)
- {
- _instance = me->GetInstanceScript();
- }
-
- void MovementInform(uint32 motionType, uint32 /*pointId*/) override
- {
- if (motionType != POINT_MOTION_TYPE)
- return;
-
- if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
- me->SetFacingToObject(akama);
- }
+ _events.Update(diff);
- void DoAction(int32 actionId) override
+ while (uint32 eventId = _events.ExecuteEvent())
{
- switch (actionId)
+ switch (eventId)
{
- case ACTION_BROKEN_SPECIAL:
- Talk(SAY_BROKEN_SPECIAL);
+ case EVENT_SPIRIT_HEAL:
+ DoCastSelf(SPELL_SPIRITBINDER_SPIRIT_HEAL);
+ _events.Repeat(Seconds(13), Seconds(16));
break;
- case ACTION_BROKEN_HAIL:
- me->SetFaction(FACTION_ASHTONGUE_DEATHSWORN);
- Talk(SAY_BROKEN_HAIL);
+ case EVENT_SPIRIT_MEND_RESET:
+ _spiritMend = false;
break;
- case ACTION_BROKEN_EMOTE:
- me->SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_STAND_STATE, UNIT_STAND_STATE_KNEEL);
+ case EVENT_CHAIN_HEAL_RESET:
+ _chainHeal = false;
break;
default:
break;
}
}
- private:
- InstanceScript* _instance;
- };
-
+ if (!UpdateVictim())
+ return;
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<npc_ashtongue_brokenAI>(creature);
+ DoMeleeAttackIfReady();
}
+
+private:
+ InstanceScript* _instance;
+ EventMap _events;
+ bool _spiritMend;
+ bool _chainHeal;
};
-// 40401 - Shade Soul Channel (serverside spell)
-class spell_shade_soul_channel_serverside : public SpellScriptLoader
+struct npc_ashtongue_broken : public ScriptedAI
{
-public:
- spell_shade_soul_channel_serverside() : SpellScriptLoader("spell_shade_soul_channel_serverside") { }
+ npc_ashtongue_broken(Creature* creature) : ScriptedAI(creature)
+ {
+ _instance = me->GetInstanceScript();
+ }
- class spell_shade_soul_channel_serverside_AuraScript : public AuraScript
+ void MovementInform(uint32 motionType, uint32 /*pointId*/) override
{
- PrepareAuraScript(spell_shade_soul_channel_serverside_AuraScript);
+ if (motionType != POINT_MOTION_TYPE)
+ return;
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo({ SPELL_SHADE_SOUL_CHANNEL_2 });
- }
+ if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
+ me->SetFacingToObject(akama);
+ }
- void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ void DoAction(int32 actionId) override
+ {
+ switch (actionId)
{
- GetTarget()->RemoveAuraFromStack(SPELL_SHADE_SOUL_CHANNEL_2);
+ case ACTION_BROKEN_SPECIAL:
+ Talk(SAY_BROKEN_SPECIAL);
+ break;
+ case ACTION_BROKEN_HAIL:
+ me->SetFaction(FACTION_ASHTONGUE_DEATHSWORN);
+ Talk(SAY_BROKEN_HAIL);
+ break;
+ case ACTION_BROKEN_EMOTE:
+ me->SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_STAND_STATE, UNIT_STAND_STATE_KNEEL);
+ break;
+ default:
+ break;
}
+ }
- void Register() override
- {
- AfterEffectRemove += AuraEffectRemoveFn(spell_shade_soul_channel_serverside_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
- }
- };
+private:
+ InstanceScript* _instance;
+};
+
+// 40401 - Shade Soul Channel (serverside spell)
+class spell_shade_soul_channel_serverside : public AuraScript
+{
+ PrepareAuraScript(spell_shade_soul_channel_serverside);
- AuraScript* GetAuraScript() const override
+ bool Validate(SpellInfo const* /*spell*/) override
{
- return new spell_shade_soul_channel_serverside_AuraScript();
+ return ValidateSpellInfo({ SPELL_SHADE_SOUL_CHANNEL_2 });
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->RemoveAuraFromStack(SPELL_SHADE_SOUL_CHANNEL_2);
+ }
+
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_shade_soul_channel_serverside::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
// 40520 - Shade Soul Channel
-class spell_shade_soul_channel : public SpellScriptLoader
+class spell_shade_soul_channel : public AuraScript
{
-public:
- spell_shade_soul_channel() : SpellScriptLoader("spell_shade_soul_channel") { }
+ PrepareAuraScript(spell_shade_soul_channel);
- class spell_shade_soul_channel_AuraScript : public AuraScript
+ void OnApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
- PrepareAuraScript(spell_shade_soul_channel_AuraScript);
-
- void OnApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
- {
- int32 const maxSlowEff = -99;
- if (aurEff->GetAmount() < maxSlowEff)
- if (AuraEffect* slowEff = GetEffect(EFFECT_0))
- slowEff->ChangeAmount(maxSlowEff);
- }
-
- void Register() override
- {
- AfterEffectApply += AuraEffectApplyFn(spell_shade_soul_channel_AuraScript::OnApply, EFFECT_0, SPELL_AURA_MOD_DECREASE_SPEED, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
- }
- };
+ int32 const maxSlowEff = -99;
+ if (aurEff->GetAmount() < maxSlowEff)
+ if (AuraEffect* slowEff = GetEffect(EFFECT_0))
+ slowEff->ChangeAmount(maxSlowEff);
+ }
- AuraScript* GetAuraScript() const override
+ void Register() override
{
- return new spell_shade_soul_channel_AuraScript();
+ AfterEffectApply += AuraEffectApplyFn(spell_shade_soul_channel::OnApply, EFFECT_0, SPELL_AURA_MOD_DECREASE_SPEED, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
}
};
void AddSC_boss_shade_of_akama()
{
- new boss_shade_of_akama();
- new npc_akama_shade();
- new npc_ashtongue_channeler();
- new npc_creature_generator_akama();
- new npc_ashtongue_sorcerer();
- new npc_ashtongue_defender();
- new npc_ashtongue_rogue();
- new npc_ashtongue_elementalist();
- new npc_ashtongue_spiritbinder();
- new npc_ashtongue_broken();
- new spell_shade_soul_channel_serverside();
- new spell_shade_soul_channel();
+ RegisterBlackTempleCreatureAI(boss_shade_of_akama);
+ RegisterBlackTempleCreatureAI(npc_akama_shade);
+ RegisterBlackTempleCreatureAI(npc_ashtongue_channeler);
+ RegisterBlackTempleCreatureAI(npc_creature_generator_akama);
+ RegisterBlackTempleCreatureAI(npc_ashtongue_sorcerer);
+ RegisterBlackTempleCreatureAI(npc_ashtongue_defender);
+ RegisterBlackTempleCreatureAI(npc_ashtongue_rogue);
+ RegisterBlackTempleCreatureAI(npc_ashtongue_elementalist);
+ RegisterBlackTempleCreatureAI(npc_ashtongue_spiritbinder);
+ RegisterBlackTempleCreatureAI(npc_ashtongue_broken);
+ RegisterAuraScript(spell_shade_soul_channel_serverside);
+ RegisterAuraScript(spell_shade_soul_channel);
}
diff --git a/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp b/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp
index c84a3504f61..ca7bc790aa1 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp
@@ -63,200 +63,165 @@ enum Actions
{
ACTION_DISABLE_VULCANO = 1
};
-
-class boss_supremus : public CreatureScript
+struct boss_supremus : public BossAI
{
-public:
- boss_supremus() : CreatureScript("boss_supremus") { }
+ boss_supremus(Creature* creature) : BossAI(creature, DATA_SUPREMUS) { }
- struct boss_supremusAI : public BossAI
+ void Reset() override
{
- boss_supremusAI(Creature* creature) : BossAI(creature, DATA_SUPREMUS) { }
+ _Reset();
+ events.SetPhase(PHASE_INITIAL);
+ me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
+ me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false);
+ }
- void Reset() override
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ summons.DespawnAll();
+ _DespawnAtEvade();
+ }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _EnterCombat();
+ ChangePhase();
+ events.ScheduleEvent(EVENT_BERSERK, Minutes(15));
+ events.ScheduleEvent(EVENT_FLAME, Seconds(20));
+ }
+
+ void ChangePhase()
+ {
+ if (events.IsInPhase(PHASE_INITIAL) || events.IsInPhase(PHASE_CHASE))
{
- _Reset();
- events.SetPhase(PHASE_INITIAL);
+ events.SetPhase(PHASE_STRIKE);
+ DummyEntryCheckPredicate pred;
+ summons.DoAction(ACTION_DISABLE_VULCANO, pred);
+ events.ScheduleEvent(EVENT_HATEFUL_STRIKE, Seconds(2), 0, PHASE_STRIKE);
+ me->RemoveAurasDueToSpell(SPELL_SNARE_SELF);
me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false);
}
-
- void EnterEvadeMode(EvadeReason /*why*/) override
- {
- summons.DespawnAll();
- _DespawnAtEvade();
- }
-
- void EnterCombat(Unit* /*who*/) override
+ else
{
- _EnterCombat();
- ChangePhase();
- events.ScheduleEvent(EVENT_BERSERK, Minutes(15));
- events.ScheduleEvent(EVENT_FLAME, Seconds(20));
+ events.SetPhase(PHASE_CHASE);
+ events.ScheduleEvent(EVENT_VOLCANO, Seconds(5), 0, PHASE_CHASE);
+ events.ScheduleEvent(EVENT_SWITCH_TARGET, Seconds(10), 0, PHASE_CHASE);
+ me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
+ me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true);
+ DoCast(SPELL_SNARE_SELF);
}
+ ResetThreatList();
+ DoZoneInCombat();
+ events.ScheduleEvent(EVENT_SWITCH_PHASE, Seconds(60));
+ }
- void ChangePhase()
- {
- if (events.IsInPhase(PHASE_INITIAL) || events.IsInPhase(PHASE_CHASE))
- {
- events.SetPhase(PHASE_STRIKE);
- DummyEntryCheckPredicate pred;
- summons.DoAction(ACTION_DISABLE_VULCANO, pred);
- events.ScheduleEvent(EVENT_HATEFUL_STRIKE, Seconds(2), 0, PHASE_STRIKE);
- me->RemoveAurasDueToSpell(SPELL_SNARE_SELF);
- me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
- me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false);
- }
- else
- {
- events.SetPhase(PHASE_CHASE);
- events.ScheduleEvent(EVENT_VOLCANO, Seconds(5), 0, PHASE_CHASE);
- events.ScheduleEvent(EVENT_SWITCH_TARGET, Seconds(10), 0, PHASE_CHASE);
- me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
- me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true);
- DoCast(SPELL_SNARE_SELF);
- }
- ResetThreatList();
- DoZoneInCombat();
- events.ScheduleEvent(EVENT_SWITCH_PHASE, Seconds(60));
- }
+ Unit* CalculateHatefulStrikeTarget()
+ {
+ uint32 health = 0;
+ Unit* target = nullptr;
- Unit* CalculateHatefulStrikeTarget()
+ for (auto* ref : me->GetThreatManager().GetUnsortedThreatList())
{
- uint32 health = 0;
- Unit* target = nullptr;
-
- for (auto* ref : me->GetThreatManager().GetUnsortedThreatList())
+ Unit* unit = ref->GetVictim();
+ if (me->IsWithinMeleeRange(unit))
{
- Unit* unit = ref->GetVictim();
- if (me->IsWithinMeleeRange(unit))
+ if (unit->GetHealth() > health)
{
- if (unit->GetHealth() > health)
- {
- health = unit->GetHealth();
- target = unit;
- }
+ health = unit->GetHealth();
+ target = unit;
}
}
-
- return target;
}
- void ExecuteEvent(uint32 eventId) override
- {
- switch (eventId)
- {
- case EVENT_BERSERK:
- DoCastSelf(SPELL_BERSERK, true);
- break;
- case EVENT_FLAME:
- DoCast(SPELL_MOLTEN_PUNCH);
- events.Repeat(Seconds(15), Seconds(20));
- break;
- case EVENT_HATEFUL_STRIKE:
- if (Unit* target = CalculateHatefulStrikeTarget())
- DoCast(target, SPELL_HATEFUL_STRIKE);
- events.Repeat(Seconds(5));
- break;
- case EVENT_SWITCH_TARGET:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true))
- {
- ResetThreatList();
- AddThreat(target, 1000000.0f);
- DoCast(target, SPELL_CHARGE);
- Talk(EMOTE_NEW_TARGET);
- }
- events.Repeat(Seconds(10));
- break;
- case EVENT_VOLCANO:
- DoCastAOE(SPELL_VOLCANIC_SUMMON, true);
- Talk(EMOTE_GROUND_CRACK);
- events.Repeat(Seconds(10));
- break;
- case EVENT_SWITCH_PHASE:
- ChangePhase();
- break;
- default:
- break;
- }
- }
-
- };
+ return target;
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void ExecuteEvent(uint32 eventId) override
{
- return GetBlackTempleAI<boss_supremusAI>(creature);
+ switch (eventId)
+ {
+ case EVENT_BERSERK:
+ DoCastSelf(SPELL_BERSERK, true);
+ break;
+ case EVENT_FLAME:
+ DoCast(SPELL_MOLTEN_PUNCH);
+ events.Repeat(Seconds(15), Seconds(20));
+ break;
+ case EVENT_HATEFUL_STRIKE:
+ if (Unit* target = CalculateHatefulStrikeTarget())
+ DoCast(target, SPELL_HATEFUL_STRIKE);
+ events.Repeat(Seconds(5));
+ break;
+ case EVENT_SWITCH_TARGET:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true))
+ {
+ ResetThreatList();
+ AddThreat(target, 1000000.0f);
+ DoCast(target, SPELL_CHARGE);
+ Talk(EMOTE_NEW_TARGET);
+ }
+ events.Repeat(Seconds(10));
+ break;
+ case EVENT_VOLCANO:
+ DoCastAOE(SPELL_VOLCANIC_SUMMON, true);
+ Talk(EMOTE_GROUND_CRACK);
+ events.Repeat(Seconds(10));
+ break;
+ case EVENT_SWITCH_PHASE:
+ ChangePhase();
+ break;
+ default:
+ break;
+ }
}
};
-class npc_molten_flame : public CreatureScript
+struct npc_molten_flame : public NullCreatureAI
{
-public:
- npc_molten_flame() : CreatureScript("npc_molten_flame") { }
+ npc_molten_flame(Creature* creature) : NullCreatureAI(creature) { }
- struct npc_molten_flameAI : public NullCreatureAI
+ void InitializeAI() override
{
- npc_molten_flameAI(Creature* creature) : NullCreatureAI(creature) { }
-
- void InitializeAI() override
- {
- float x, y, z;
- me->GetNearPoint(me, x, y, z, 1, 100.0f, frand(0.f, 2.f * float(M_PI)));
- me->GetMotionMaster()->MovePoint(0, x, y, z);
- DoCastSelf(SPELL_MOLTEN_FLAME, true);
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<npc_molten_flameAI>(creature);
+ float x, y, z;
+ me->GetNearPoint(me, x, y, z, 1, 100.0f, frand(0.f, 2.f * float(M_PI)));
+ me->GetMotionMaster()->MovePoint(0, x, y, z);
+ DoCastSelf(SPELL_MOLTEN_FLAME, true);
}
};
-class npc_volcano : public CreatureScript
+struct npc_volcano : public NullCreatureAI
{
-public:
- npc_volcano() : CreatureScript("npc_volcano") { }
+ npc_volcano(Creature* creature) : NullCreatureAI(creature) { }
- struct npc_volcanoAI : public NullCreatureAI
+ void Reset() override
{
- npc_volcanoAI(Creature* creature) : NullCreatureAI(creature) { }
-
- void Reset() override
+ _scheduler.Schedule(Seconds(3), [this](TaskContext /*context*/)
{
- _scheduler.Schedule(Seconds(3), [this](TaskContext /*context*/)
- {
- DoCastSelf(SPELL_VOLCANIC_ERUPTION);
- });
- }
-
- void DoAction(int32 action) override
- {
- if (action == ACTION_DISABLE_VULCANO)
- {
- me->RemoveAurasDueToSpell(SPELL_VOLCANIC_ERUPTION);
- me->RemoveAurasDueToSpell(SPELL_VOLCANIC_GEYSER);
- }
- }
+ DoCastSelf(SPELL_VOLCANIC_ERUPTION);
+ });
+ }
- void UpdateAI(uint32 diff) override
+ void DoAction(int32 action) override
+ {
+ if (action == ACTION_DISABLE_VULCANO)
{
- _scheduler.Update(diff);
+ me->RemoveAurasDueToSpell(SPELL_VOLCANIC_ERUPTION);
+ me->RemoveAurasDueToSpell(SPELL_VOLCANIC_GEYSER);
}
+ }
- private:
- TaskScheduler _scheduler;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
+ void UpdateAI(uint32 diff) override
{
- return GetBlackTempleAI<npc_volcanoAI>(creature);
+ _scheduler.Update(diff);
}
+
+private:
+ TaskScheduler _scheduler;
};
void AddSC_boss_supremus()
{
- new boss_supremus();
- new npc_molten_flame();
- new npc_volcano();
+ RegisterBlackTempleCreatureAI(boss_supremus);
+ RegisterBlackTempleCreatureAI(npc_molten_flame);
+ RegisterBlackTempleCreatureAI(npc_volcano);
}
diff --git a/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp b/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp
index 67ed253f247..496212ed692 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp
@@ -69,14 +69,13 @@ enum Spells
SPELL_SPIRIT_VOLLEY = 40314,
SPELL_SPIRIT_SHIELD = 40322,
SPELL_SPIRIT_LANCE = 40157
-
};
enum Npcs
{
- NPC_DOOM_BLOSSOM = 23123,
- NPC_SHADOWY_CONSTRUCT = 23111,
- NPC_VENGEFUL_SPIRIT = 23109 //Npc controlled by player
+ NPC_DOOM_BLOSSOM = 23123,
+ NPC_SHADOWY_CONSTRUCT = 23111,
+ NPC_VENGEFUL_SPIRIT = 23109 //Npc controlled by player
};
enum Events
@@ -108,411 +107,348 @@ uint32 const SkeletronSpells[4] =
SPELL_SUMMON_SKELETRON_4
};
-class boss_teron_gorefiend : public CreatureScript
+struct boss_teron_gorefiend : public BossAI
{
-public:
- boss_teron_gorefiend() : CreatureScript("boss_teron_gorefiend") { }
+ boss_teron_gorefiend(Creature* creature) : BossAI(creature, DATA_TERON_GOREFIEND) { }
- struct boss_teron_gorefiendAI : public BossAI
+ void Reset() override
{
- boss_teron_gorefiendAI(Creature* creature) : BossAI(creature, DATA_TERON_GOREFIEND), _intro(false)
+ _Reset();
+ if (instance->GetData(DATA_TERON_GOREFIEND_INTRO))
{
- creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
- creature->SetReactState(REACT_PASSIVE);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ me->SetReactState(REACT_PASSIVE);
}
+ }
- void EnterCombat(Unit* /*who*/) override
- {
- _EnterCombat();
- Talk(SAY_AGGRO);
- events.SetPhase(PHASE_COMBAT);
- events.ScheduleEvent(EVENT_ENRAGE, Minutes(10));
- events.ScheduleEvent(EVENT_INCINERATE, Seconds(12));
- events.ScheduleEvent(EVENT_SUMMON_DOOM_BLOSSOM, Seconds(8));
- events.ScheduleEvent(EVENT_SHADOW_DEATH, Seconds(8));
- events.ScheduleEvent(EVENT_CRUSHING_SHADOWS, Seconds(18));
- }
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _EnterCombat();
+ Talk(SAY_AGGRO);
+ events.SetPhase(PHASE_COMBAT);
+ events.ScheduleEvent(EVENT_ENRAGE, Minutes(10));
+ events.ScheduleEvent(EVENT_INCINERATE, Seconds(12));
+ events.ScheduleEvent(EVENT_SUMMON_DOOM_BLOSSOM, Seconds(8));
+ events.ScheduleEvent(EVENT_SHADOW_DEATH, Seconds(8));
+ events.ScheduleEvent(EVENT_CRUSHING_SHADOWS, Seconds(18));
+ }
- void EnterEvadeMode(EvadeReason /*why*/) override
- {
- DoCast(SPELL_SHADOW_OF_DEATH_REMOVE);
- summons.DespawnAll();
- _DespawnAtEvade();
- }
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ DoCast(SPELL_SHADOW_OF_DEATH_REMOVE);
+ summons.DespawnAll();
+ _DespawnAtEvade();
+ }
- void DoAction(int32 action) override
+ void DoAction(int32 action) override
+ {
+ if (action == ACTION_START_INTRO && me->IsAlive())
{
- if (action == ACTION_START_INTRO && !_intro && me->IsAlive())
- {
- _intro = true;
- Talk(SAY_INTRO);
- events.SetPhase(PHASE_INTRO);
- events.ScheduleEvent(EVENT_FINISH_INTRO, Seconds(20));
- }
+ instance->SetData(DATA_TERON_GOREFIEND_INTRO, 0);
+ Talk(SAY_INTRO);
+ events.SetPhase(PHASE_INTRO);
+ events.ScheduleEvent(EVENT_FINISH_INTRO, Seconds(20));
}
+ }
- void KilledUnit(Unit* victim) override
- {
- if (victim->GetTypeId() == TYPEID_PLAYER)
- Talk(SAY_SLAY);
- }
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SLAY);
+ }
- void JustDied(Unit* /*killer*/) override
- {
- Talk(SAY_DEATH);
- DoCast(SPELL_SHADOW_OF_DEATH_REMOVE);
- _JustDied();
- }
+ void JustDied(Unit* /*killer*/) override
+ {
+ Talk(SAY_DEATH);
+ DoCast(SPELL_SHADOW_OF_DEATH_REMOVE);
+ _JustDied();
+ }
- void UpdateAI(uint32 diff) override
- {
- if (!events.IsInPhase(PHASE_INTRO) && !UpdateVictim())
- return;
+ void UpdateAI(uint32 diff) override
+ {
+ if (!events.IsInPhase(PHASE_INTRO) && !UpdateVictim())
+ return;
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- events.Update(diff);
+ events.Update(diff);
- while (uint32 eventId = events.ExecuteEvent())
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- switch (eventId)
- {
- case EVENT_ENRAGE:
- DoCast(SPELL_BERSERK);
- break;
- case EVENT_INCINERATE:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, SPELL_INCINERATE);
- Talk(SAY_INCINERATE);
- events.Repeat(Seconds(12), Seconds(20));
- break;
- case EVENT_SUMMON_DOOM_BLOSSOM:
- DoCastSelf(SPELL_SUMMON_DOOM_BLOSSOM, true);
- Talk(SAY_BLOSSOM);
- events.Repeat(Seconds(30), Seconds(40));
- break;
- case EVENT_SHADOW_DEATH:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true, true, -SPELL_SPIRITUAL_VENGEANCE))
- DoCast(target, SPELL_SHADOW_OF_DEATH);
- events.Repeat(Seconds(30), Seconds(35));
- break;
- case EVENT_CRUSHING_SHADOWS:
- me->CastCustomSpell(SPELL_CRUSHING_SHADOWS, SPELLVALUE_MAX_TARGETS, 5, me);
- Talk(SAY_CRUSHING);
- events.Repeat(Seconds(18), Seconds(30));
- break;
- case EVENT_FINISH_INTRO:
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
- me->SetReactState(REACT_AGGRESSIVE);
- break;
- default:
- break;
- }
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ case EVENT_ENRAGE:
+ DoCast(SPELL_BERSERK);
+ break;
+ case EVENT_INCINERATE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ DoCast(target, SPELL_INCINERATE);
+ Talk(SAY_INCINERATE);
+ events.Repeat(Seconds(12), Seconds(20));
+ break;
+ case EVENT_SUMMON_DOOM_BLOSSOM:
+ DoCastSelf(SPELL_SUMMON_DOOM_BLOSSOM, true);
+ Talk(SAY_BLOSSOM);
+ events.Repeat(Seconds(30), Seconds(40));
+ break;
+ case EVENT_SHADOW_DEATH:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true, true, -SPELL_SPIRITUAL_VENGEANCE))
+ DoCast(target, SPELL_SHADOW_OF_DEATH);
+ events.Repeat(Seconds(30), Seconds(35));
+ break;
+ case EVENT_CRUSHING_SHADOWS:
+ me->CastCustomSpell(SPELL_CRUSHING_SHADOWS, SPELLVALUE_MAX_TARGETS, 5, me);
+ Talk(SAY_CRUSHING);
+ events.Repeat(Seconds(18), Seconds(30));
+ break;
+ case EVENT_FINISH_INTRO:
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
+ me->SetReactState(REACT_AGGRESSIVE);
+ break;
+ default:
+ break;
}
- DoMeleeAttackIfReady();
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
- private:
- bool _intro;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<boss_teron_gorefiendAI>(creature);
+ DoMeleeAttackIfReady();
}
};
-class npc_doom_blossom : public CreatureScript
+struct npc_doom_blossom : public NullCreatureAI
{
-public:
- npc_doom_blossom() : CreatureScript("npc_doom_blossom") { }
- struct npc_doom_blossomAI : public NullCreatureAI
- {
- npc_doom_blossomAI(Creature* creature) : NullCreatureAI(creature), _instance(me->GetInstanceScript()) { }
+ npc_doom_blossom(Creature* creature) : NullCreatureAI(creature), _instance(me->GetInstanceScript()) { }
- void Reset() override
- {
- /* Workaround - Until SMSG_SET_PLAY_HOVER_ANIM be implemented */
- Position pos;
- pos.Relocate(me);
- pos.m_positionZ += 8.0f;
- me->GetMotionMaster()->MoveTakeoff(0, pos);
-
- DoCast(SPELL_SUMMON_BLOSSOM_MOVE_TARGET);
- _scheduler.CancelAll();
- me->SetInCombatWithZone();
- _scheduler.Schedule(Seconds(12), [this](TaskContext shadowBolt)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, SPELL_SHADOWBOLT);
-
- shadowBolt.Repeat(Seconds(2));
- });
- }
-
- void UpdateAI(uint32 diff) override
+ void Reset() override
+ {
+ /* Workaround - Until SMSG_SET_PLAY_HOVER_ANIM be implemented */
+ Position pos;
+ pos.Relocate(me);
+ pos.m_positionZ += 8.0f;
+ me->GetMotionMaster()->MoveTakeoff(0, pos);
+
+ DoCast(SPELL_SUMMON_BLOSSOM_MOVE_TARGET);
+ _scheduler.CancelAll();
+ me->SetInCombatWithZone();
+ _scheduler.Schedule(Seconds(12), [this](TaskContext shadowBolt)
{
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- _scheduler.Update(diff);
- }
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ DoCast(target, SPELL_SHADOWBOLT);
- private:
- TaskScheduler _scheduler;
- InstanceScript* _instance;
- };
+ shadowBolt.Repeat(Seconds(2));
+ });
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void UpdateAI(uint32 diff) override
{
- return GetBlackTempleAI<npc_doom_blossomAI>(creature);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ _scheduler.Update(diff);
}
+
+private:
+ TaskScheduler _scheduler;
+ InstanceScript* _instance;
};
-class npc_shadowy_construct : public CreatureScript
+struct npc_shadowy_construct : public ScriptedAI
{
-public:
- npc_shadowy_construct() : CreatureScript("npc_shadowy_construct") { }
+ npc_shadowy_construct(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript())
+ {
+ //This creature must be immune everything, except spells of Vengeful Spirit.
+ creature->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true);
+ creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_MAGIC, true);
+ }
- struct npc_shadowy_constructAI : public ScriptedAI
+ void Reset() override
{
- npc_shadowy_constructAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript())
+ if (_instance->GetBossState(DATA_TERON_GOREFIEND) != IN_PROGRESS)
{
- //This creature must be immune everything, except spells of Vengeful Spirit.
- creature->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true);
- creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_MAGIC, true);
+ me->DespawnOrUnsummon();
+ return;
}
- void Reset() override
+ targetGUID.Clear();
+ _scheduler.CancelAll();
+ _scheduler.Schedule(Seconds(12), [this](TaskContext atrophy)
{
- if (_instance->GetBossState(DATA_TERON_GOREFIEND) != IN_PROGRESS)
+ DoCastVictim(SPELL_ATROPHY);
+ atrophy.Repeat(Seconds(10), Seconds(12));
+ });
+ _scheduler.Schedule(Milliseconds(200), [this](TaskContext checkPlayer)
+ {
+ if (Unit* target = ObjectAccessor::GetUnit(*me, targetGUID))
{
- me->DespawnOrUnsummon();
- return;
+ if (!target->IsAlive() || !me->CanCreatureAttack(target))
+ SelectNewTarget();
}
+ else
+ SelectNewTarget();
- targetGUID.Clear();
- _scheduler.CancelAll();
- _scheduler.Schedule(Seconds(12), [this](TaskContext atrophy)
- {
- DoCastVictim(SPELL_ATROPHY);
- atrophy.Repeat(Seconds(10), Seconds(12));
- });
- _scheduler.Schedule(Milliseconds(200), [this](TaskContext checkPlayer)
- {
- if (Unit* target = ObjectAccessor::GetUnit(*me, targetGUID))
- {
- if (!target->IsAlive() || !me->CanCreatureAttack(target))
- SelectNewTarget();
- }
- else
- SelectNewTarget();
+ checkPlayer.Repeat(Seconds(1));
+ });
- checkPlayer.Repeat(Seconds(1));
- });
+ if (Creature* teron = _instance->GetCreature(DATA_TERON_GOREFIEND))
+ teron->AI()->JustSummoned(me);
- if (Creature* teron = _instance->GetCreature(DATA_TERON_GOREFIEND))
- teron->AI()->JustSummoned(me);
+ SelectNewTarget();
+ }
- SelectNewTarget();
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- void UpdateAI(uint32 diff) override
+ _scheduler.Update(diff, [this]
{
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- _scheduler.Update(diff, [this]
- {
- DoMeleeAttackIfReady();
- });
- }
+ DoMeleeAttackIfReady();
+ });
+ }
- void SelectNewTarget()
+ void SelectNewTarget()
+ {
+ if (Creature* teron = _instance->GetCreature(DATA_TERON_GOREFIEND))
{
- if (Creature* teron = _instance->GetCreature(DATA_TERON_GOREFIEND))
+ Unit* target = teron->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, true, -SPELL_SPIRITUAL_VENGEANCE);
+ // He should target Vengeful Spirits only if has no other player available
+ if (!target)
+ target = teron->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0);
+
+ if (target)
{
- Unit* target = teron->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, true, -SPELL_SPIRITUAL_VENGEANCE);
- // He should target Vengeful Spirits only if has no other player available
- if (!target)
- target = teron->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0);
-
- if (target)
- {
- ResetThreatList();
- AttackStart(target);
- AddThreat(target, 1000000.0f);
- targetGUID = target->GetGUID();
- }
+ ResetThreatList();
+ AttackStart(target);
+ AddThreat(target, 1000000.0f);
+ targetGUID = target->GetGUID();
}
}
-
- private:
- TaskScheduler _scheduler;
- InstanceScript* _instance;
- ObjectGuid targetGUID;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<npc_shadowy_constructAI>(creature);
}
-};
-
-class at_teron_gorefiend_entrance : public AreaTriggerScript
-{
-public:
- at_teron_gorefiend_entrance() : AreaTriggerScript("at_teron_gorefiend_entrance") { }
-
- bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
- {
- if (InstanceScript* instance = player->GetInstanceScript())
- if (Creature* teron = instance->GetCreature(DATA_TERON_GOREFIEND))
- teron->AI()->DoAction(ACTION_START_INTRO);
- return true;
- }
+private:
+ TaskScheduler _scheduler;
+ InstanceScript* _instance;
+ ObjectGuid targetGUID;
};
// 40251 - Shadow of Death
-class spell_teron_gorefiend_shadow_of_death : public SpellScriptLoader
+class spell_teron_gorefiend_shadow_of_death : public AuraScript
{
- public:
- spell_teron_gorefiend_shadow_of_death() : SpellScriptLoader("spell_teron_gorefiend_shadow_of_death") { }
+ PrepareAuraScript(spell_teron_gorefiend_shadow_of_death);
- class spell_teron_gorefiend_shadow_of_death_AuraScript : public AuraScript
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareAuraScript(spell_teron_gorefiend_shadow_of_death_AuraScript);
-
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_SUMMON_SPIRIT,
- SPELL_POSSESS_SPIRIT_IMMUNE,
- SPELL_SPIRITUAL_VENGEANCE,
- SPELL_SUMMON_SKELETRON_1,
- SPELL_SUMMON_SKELETRON_2,
- SPELL_SUMMON_SKELETRON_3,
- SPELL_SUMMON_SKELETRON_4
- });
- }
-
- void Absorb(AuraEffect* /*aurEff*/, DamageInfo& /*dmgInfo*/, uint32& /*absorbAmount*/)
- {
- PreventDefaultAction();
- }
-
- void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
- {
- Unit* target = GetTarget();
- target->CastSpell(target, SPELL_SUMMON_SPIRIT, true);
+ SPELL_SUMMON_SPIRIT,
+ SPELL_POSSESS_SPIRIT_IMMUNE,
+ SPELL_SPIRITUAL_VENGEANCE,
+ SPELL_SUMMON_SKELETRON_1,
+ SPELL_SUMMON_SKELETRON_2,
+ SPELL_SUMMON_SKELETRON_3,
+ SPELL_SUMMON_SKELETRON_4
+ });
+ }
- for (uint8 i = 0; i < 4; ++i)
- target->CastSpell(target, SkeletronSpells[i], true);
+ void Absorb(AuraEffect* /*aurEff*/, DamageInfo& /*dmgInfo*/, uint32& /*absorbAmount*/)
+ {
+ PreventDefaultAction();
+ }
- target->CastSpell(target, SPELL_POSSESS_SPIRIT_IMMUNE, true);
- target->CastSpell(target, SPELL_SPIRITUAL_VENGEANCE, true);
- }
- }
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
+ {
+ Unit* target = GetTarget();
+ target->CastSpell(target, SPELL_SUMMON_SPIRIT, true);
- void Register() override
- {
- OnEffectAbsorb += AuraEffectAbsorbFn(spell_teron_gorefiend_shadow_of_death_AuraScript::Absorb, EFFECT_0);
- AfterEffectRemove += AuraEffectRemoveFn(spell_teron_gorefiend_shadow_of_death_AuraScript::OnRemove, EFFECT_1, SPELL_AURA_OVERRIDE_CLASS_SCRIPTS, AURA_EFFECT_HANDLE_REAL);
- }
- };
+ for (uint8 i = 0; i < 4; ++i)
+ target->CastSpell(target, SkeletronSpells[i], true);
- AuraScript* GetAuraScript() const override
- {
- return new spell_teron_gorefiend_shadow_of_death_AuraScript();
+ target->CastSpell(target, SPELL_POSSESS_SPIRIT_IMMUNE, true);
+ target->CastSpell(target, SPELL_SPIRITUAL_VENGEANCE, true);
}
+ }
+
+ void Register() override
+ {
+ OnEffectAbsorb += AuraEffectAbsorbFn(spell_teron_gorefiend_shadow_of_death::Absorb, EFFECT_0);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_teron_gorefiend_shadow_of_death::OnRemove, EFFECT_1, SPELL_AURA_OVERRIDE_CLASS_SCRIPTS, AURA_EFFECT_HANDLE_REAL);
+ }
};
// 40268 - Spiritual Vengeance
-class spell_teron_gorefiend_spiritual_vengeance : public SpellScriptLoader
+class spell_teron_gorefiend_spiritual_vengeance : public AuraScript
{
- public:
- spell_teron_gorefiend_spiritual_vengeance() : SpellScriptLoader("spell_teron_gorefiend_spiritual_vengeance") { }
+ PrepareAuraScript(spell_teron_gorefiend_spiritual_vengeance);
- class spell_teron_gorefiend_spiritual_vengeance_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_teron_gorefiend_spiritual_vengeance_AuraScript);
-
- void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- GetTarget()->KillSelf();
- }
-
- void Register() override
- {
- AfterEffectRemove += AuraEffectRemoveFn(spell_teron_gorefiend_spiritual_vengeance_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_POSSESS, AURA_EFFECT_HANDLE_REAL);
- AfterEffectRemove += AuraEffectRemoveFn(spell_teron_gorefiend_spiritual_vengeance_AuraScript::OnRemove, EFFECT_2, SPELL_AURA_MOD_PACIFY_SILENCE, AURA_EFFECT_HANDLE_REAL);
- }
- };
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->KillSelf();
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_teron_gorefiend_spiritual_vengeance_AuraScript();
- }
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_teron_gorefiend_spiritual_vengeance::OnRemove, EFFECT_0, SPELL_AURA_MOD_POSSESS, AURA_EFFECT_HANDLE_REAL);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_teron_gorefiend_spiritual_vengeance::OnRemove, EFFECT_2, SPELL_AURA_MOD_PACIFY_SILENCE, AURA_EFFECT_HANDLE_REAL);
+ }
};
// 41999 - Shadow of Death Remove
-class spell_teron_gorefiend_shadow_of_death_remove : public SpellScriptLoader
+class spell_teron_gorefiend_shadow_of_death_remove : public SpellScript
{
- public:
- spell_teron_gorefiend_shadow_of_death_remove() : SpellScriptLoader("spell_teron_gorefiend_shadow_of_death_remove") { }
+ PrepareSpellScript(spell_teron_gorefiend_shadow_of_death_remove);
- class spell_teron_gorefiend_shadow_of_death_remove_SpellScript : public SpellScript
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareSpellScript(spell_teron_gorefiend_shadow_of_death_remove_SpellScript);
+ SPELL_SHADOW_OF_DEATH,
+ SPELL_POSSESS_SPIRIT_IMMUNE,
+ SPELL_SPIRITUAL_VENGEANCE
+ });
+ }
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_SHADOW_OF_DEATH,
- SPELL_POSSESS_SPIRIT_IMMUNE,
- SPELL_SPIRITUAL_VENGEANCE
- });
- }
+ void RemoveAuras()
+ {
+ Unit* target = GetHitUnit();
- void RemoveAuras()
- {
- Unit* target = GetHitUnit();
+ target->RemoveAurasDueToSpell(SPELL_POSSESS_SPIRIT_IMMUNE);
+ target->RemoveAurasDueToSpell(SPELL_SPIRITUAL_VENGEANCE);
+ target->RemoveAurasDueToSpell(SPELL_SHADOW_OF_DEATH);
+ }
- target->RemoveAurasDueToSpell(SPELL_POSSESS_SPIRIT_IMMUNE);
- target->RemoveAurasDueToSpell(SPELL_SPIRITUAL_VENGEANCE);
- target->RemoveAurasDueToSpell(SPELL_SHADOW_OF_DEATH);
- }
+ void Register() override
+ {
+ OnHit += SpellHitFn(spell_teron_gorefiend_shadow_of_death_remove::RemoveAuras);
+ }
+};
- void Register() override
- {
- OnHit += SpellHitFn(spell_teron_gorefiend_shadow_of_death_remove_SpellScript::RemoveAuras);
- }
+class at_teron_gorefiend_entrance : public OnlyOnceAreaTriggerScript
+{
+public:
+ at_teron_gorefiend_entrance() : OnlyOnceAreaTriggerScript("at_teron_gorefiend_entrance") { }
- };
+ bool _OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
+ {
+ if (InstanceScript* instance = player->GetInstanceScript())
+ if (Creature* teron = instance->GetCreature(DATA_TERON_GOREFIEND))
+ teron->AI()->DoAction(ACTION_START_INTRO);
- SpellScript* GetSpellScript() const override
- {
- return new spell_teron_gorefiend_shadow_of_death_remove_SpellScript();
- }
+ return true;
+ }
};
void AddSC_boss_teron_gorefiend()
{
- new boss_teron_gorefiend();
- new npc_doom_blossom();
- new npc_shadowy_construct();
+ RegisterBlackTempleCreatureAI(boss_teron_gorefiend);
+ RegisterBlackTempleCreatureAI(npc_doom_blossom);
+ RegisterBlackTempleCreatureAI(npc_shadowy_construct);
+ RegisterAuraScript(spell_teron_gorefiend_shadow_of_death);
+ RegisterAuraScript(spell_teron_gorefiend_spiritual_vengeance);
+ RegisterSpellScript(spell_teron_gorefiend_shadow_of_death_remove);
new at_teron_gorefiend_entrance();
- new spell_teron_gorefiend_shadow_of_death();
- new spell_teron_gorefiend_spiritual_vengeance();
- new spell_teron_gorefiend_shadow_of_death_remove();
}
diff --git a/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp b/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp
index b49ad6e3f20..4a35acc20db 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp
@@ -28,220 +28,207 @@
enum Texts
{
- SAY_AGGRO = 0,
- SAY_NEEDLE = 1,
- SAY_SLAY = 2,
- SAY_SPECIAL = 3,
- SAY_ENRAGE = 4,
- SAY_DEATH = 5
+ SAY_AGGRO = 0,
+ SAY_NEEDLE = 1,
+ SAY_SLAY = 2,
+ SAY_SPECIAL = 3,
+ SAY_ENRAGE = 4,
+ SAY_DEATH = 5
};
enum Spells
{
- SPELL_NEEDLE_SPINE_TARGETING = 39992,
- SPELL_NEEDLE_SPINE = 39835,
- SPELL_TIDAL_BURST = 39878,
- SPELL_TIDAL_SHIELD = 39872,
- SPELL_IMPALING_SPINE = 39837,
- SPELL_CREATE_NAJENTUS_SPINE = 39956,
- SPELL_HURL_SPINE = 39948,
- SPELL_BERSERK = 26662
-
+ SPELL_NEEDLE_SPINE_TARGETING = 39992,
+ SPELL_NEEDLE_SPINE = 39835,
+ SPELL_TIDAL_BURST = 39878,
+ SPELL_TIDAL_SHIELD = 39872,
+ SPELL_IMPALING_SPINE = 39837,
+ SPELL_CREATE_NAJENTUS_SPINE = 39956,
+ SPELL_HURL_SPINE = 39948,
+ SPELL_BERSERK = 26662
};
enum Events
{
- EVENT_BERSERK = 1,
- EVENT_YELL = 2,
- EVENT_NEEDLE = 3,
- EVENT_SPINE = 4,
- EVENT_SHIELD = 5
+ EVENT_BERSERK = 1,
+ EVENT_YELL = 2,
+ EVENT_NEEDLE = 3,
+ EVENT_SPINE = 4,
+ EVENT_SHIELD = 5
};
-class boss_najentus : public CreatureScript
+enum Misc
{
-public:
- boss_najentus() : CreatureScript("boss_najentus") { }
-
- struct boss_najentusAI : public BossAI
- {
- boss_najentusAI(Creature* creature) : BossAI(creature, DATA_HIGH_WARLORD_NAJENTUS) { }
-
- void Reset() override
- {
- _Reset();
- SpineTargetGUID.Clear();
- }
-
- void EnterEvadeMode(EvadeReason /*why*/) override
- {
- _DespawnAtEvade();
- }
+ DATA_REMOVE_IMPALING_SPINE = 1,
+ ACTION_RESET_IMPALING_TARGET = 2
+};
- void KilledUnit(Unit* victim) override
- {
- if (victim->GetTypeId() == TYPEID_PLAYER)
- Talk(SAY_SLAY);
- }
+struct boss_najentus : public BossAI
+{
+ boss_najentus(Creature* creature) : BossAI(creature, DATA_HIGH_WARLORD_NAJENTUS) { }
- void JustDied(Unit* /*killer*/) override
- {
- _JustDied();
- Talk(SAY_DEATH);
- }
+ void Reset() override
+ {
+ _Reset();
+ _spineTargetGUID.Clear();
+ }
- void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
- {
- if (spell->Id == SPELL_HURL_SPINE && me->HasAura(SPELL_TIDAL_SHIELD))
- {
- me->RemoveAurasDueToSpell(SPELL_TIDAL_SHIELD);
- DoCastSelf(SPELL_TIDAL_BURST, true);
- events.RescheduleEvent(EVENT_SPINE, Seconds(2));
- }
- }
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ _EnterEvadeMode();
+ _DespawnAtEvade();
+ }
- void EnterCombat(Unit* /*who*/) override
- {
- _EnterCombat();
- Talk(SAY_AGGRO);
- events.ScheduleEvent(EVENT_NEEDLE, Seconds(2));
- events.ScheduleEvent(EVENT_SHIELD, Seconds(60));
- events.ScheduleEvent(EVENT_SPINE, Seconds(30));
- events.ScheduleEvent(EVENT_BERSERK, Seconds(480));
- events.ScheduleEvent(EVENT_YELL, Seconds(45), Seconds(100));
- }
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SLAY);
+ }
- bool RemoveImpalingSpine()
- {
- if (!SpineTargetGUID)
- return false;
-
- Unit* target = ObjectAccessor::GetUnit(*me, SpineTargetGUID);
- if (target && target->HasAura(SPELL_IMPALING_SPINE))
- target->RemoveAurasDueToSpell(SPELL_IMPALING_SPINE);
- SpineTargetGUID.Clear();
- return true;
- }
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ Talk(SAY_DEATH);
+ }
- void ExecuteEvent(uint32 eventId) override
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
+ {
+ if (spell->Id == SPELL_HURL_SPINE && me->HasAura(SPELL_TIDAL_SHIELD))
{
- switch (eventId)
- {
- case EVENT_SHIELD:
- DoCastSelf(SPELL_TIDAL_SHIELD, true);
- events.RescheduleEvent(EVENT_SPINE, Seconds(50));
- events.Repeat(Seconds(55), Seconds(60));
- break;
- case EVENT_BERSERK:
- Talk(SAY_ENRAGE);
- DoCastSelf(SPELL_BERSERK, true);
- break;
- case EVENT_SPINE:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 200.0f, true))
- {
- DoCast(target, SPELL_IMPALING_SPINE, true);
- SpineTargetGUID = target->GetGUID();
- //must let target summon, otherwise you cannot click the spine
- target->SummonGameObject(GO_NAJENTUS_SPINE, *target, QuaternionData(), 30);
- Talk(SAY_NEEDLE);
- }
- events.Repeat(Seconds(20), Seconds(25));
- break;
- case EVENT_NEEDLE:
- DoCastSelf(SPELL_NEEDLE_SPINE_TARGETING, true);
- events.Repeat(Seconds(2));
- break;
- case EVENT_YELL:
- Talk(SAY_SPECIAL);
- events.Repeat(Seconds(25), Seconds(100));
- break;
- default:
- break;
- }
+ me->RemoveAurasDueToSpell(SPELL_TIDAL_SHIELD);
+ DoCastSelf(SPELL_TIDAL_BURST, true);
+ events.RescheduleEvent(EVENT_SPINE, Seconds(2));
}
+ }
- private:
- ObjectGuid SpineTargetGUID;
- };
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _EnterCombat();
+ Talk(SAY_AGGRO);
+ events.ScheduleEvent(EVENT_NEEDLE, Seconds(2));
+ events.ScheduleEvent(EVENT_SHIELD, Seconds(60));
+ events.ScheduleEvent(EVENT_SPINE, Seconds(30));
+ events.ScheduleEvent(EVENT_BERSERK, Seconds(480));
+ events.ScheduleEvent(EVENT_YELL, Seconds(45), Seconds(100));
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ uint32 GetData(uint32 data) const override
{
- return GetBlackTempleAI<boss_najentusAI>(creature);
+ if (data == DATA_REMOVE_IMPALING_SPINE)
+ return RemoveImpalingSpine() ? 1 : 0;
+ return 0;
}
-};
-class go_najentus_spine : public GameObjectScript
-{
-public:
- go_najentus_spine() : GameObjectScript("go_najentus_spine") { }
+ void DoAction(int32 actionId) override
+ {
+ if (actionId == ACTION_RESET_IMPALING_TARGET)
+ _spineTargetGUID.Clear();
+ }
- struct go_najentus_spineAI : public GameObjectAI
+ bool RemoveImpalingSpine() const
{
- go_najentus_spineAI(GameObject* go) : GameObjectAI(go), instance(go->GetInstanceScript()) { }
+ if (!_spineTargetGUID)
+ return false;
- InstanceScript* instance;
+ Unit* target = ObjectAccessor::GetUnit(*me, _spineTargetGUID);
+ if (target && target->HasAura(SPELL_IMPALING_SPINE))
+ target->RemoveAurasDueToSpell(SPELL_IMPALING_SPINE);
+ return true;
+ }
- bool GossipHello(Player* player) override
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
{
- if (Creature* najentus = instance->GetCreature(DATA_HIGH_WARLORD_NAJENTUS))
- {
- if (ENSURE_AI(boss_najentus::boss_najentusAI, najentus->AI())->RemoveImpalingSpine())
+ case EVENT_SHIELD:
+ DoCastSelf(SPELL_TIDAL_SHIELD, true);
+ events.RescheduleEvent(EVENT_SPINE, Seconds(50));
+ events.Repeat(Seconds(55), Seconds(60));
+ break;
+ case EVENT_BERSERK:
+ Talk(SAY_ENRAGE);
+ DoCastSelf(SPELL_BERSERK, true);
+ break;
+ case EVENT_SPINE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 200.0f, true))
{
- me->CastSpell(player, SPELL_CREATE_NAJENTUS_SPINE, true);
- me->Delete();
+ DoCast(target, SPELL_IMPALING_SPINE, true);
+ _spineTargetGUID = target->GetGUID();
+ //must let target summon, otherwise you cannot click the spine
+ target->SummonGameObject(GO_NAJENTUS_SPINE, *target, QuaternionData(), 30);
+ Talk(SAY_NEEDLE);
}
- }
- return true;
+ events.Repeat(Seconds(20), Seconds(25));
+ break;
+ case EVENT_NEEDLE:
+ DoCastSelf(SPELL_NEEDLE_SPINE_TARGETING, true);
+ events.Repeat(Seconds(2));
+ break;
+ case EVENT_YELL:
+ Talk(SAY_SPECIAL);
+ events.Repeat(Seconds(25), Seconds(100));
+ break;
+ default:
+ break;
}
- };
-
- GameObjectAI* GetAI(GameObject* go) const override
- {
- return GetBlackTempleAI<go_najentus_spineAI>(go);
}
+
+private:
+ ObjectGuid _spineTargetGUID;
};
-// 39992 - Needle Spine Targeting
-class spell_najentus_needle_spine : public SpellScriptLoader
+struct go_najentus_spine : public GameObjectAI
{
- public:
- spell_najentus_needle_spine() : SpellScriptLoader("spell_najentus_needle_spine") { }
+ go_najentus_spine(GameObject* go) : GameObjectAI(go), _instance(go->GetInstanceScript()) { }
- class spell_najentus_needle_spine_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_najentus_needle_spine_SpellScript);
+ bool GossipHello(Player* player) override
+ {
+ if (!_instance)
+ return false;
- bool Validate(SpellInfo const* /*spellInfo*/) override
+ if (Creature* najentus = _instance->GetCreature(DATA_HIGH_WARLORD_NAJENTUS))
+ if (najentus->AI()->GetData(DATA_REMOVE_IMPALING_SPINE))
{
- return ValidateSpellInfo({ SPELL_NEEDLE_SPINE });
+ najentus->AI()->DoAction(ACTION_RESET_IMPALING_TARGET);
+ me->CastSpell(player, SPELL_CREATE_NAJENTUS_SPINE, true);
+ me->Delete();
}
+ return true;
+ }
+private:
+ InstanceScript* _instance;
+};
- void FilterTargets(std::list<WorldObject*>& targets)
- {
- targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_IMPALING_SPINE));
- }
+// 39992 - Needle Spine Targeting
+class spell_najentus_needle_spine : public SpellScript
+{
+ PrepareSpellScript(spell_najentus_needle_spine);
- void HandleScript(SpellEffIndex /*effIndex*/)
- {
- GetCaster()->CastSpell(GetHitUnit(), SPELL_NEEDLE_SPINE, true);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_NEEDLE_SPINE });
+ }
- void Register() override
- {
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_najentus_needle_spine_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
- OnEffectHitTarget += SpellEffectFn(spell_najentus_needle_spine_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_IMPALING_SPINE));
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_najentus_needle_spine_SpellScript();
- }
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->CastSpell(GetHitUnit(), SPELL_NEEDLE_SPINE, true);
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_najentus_needle_spine::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnEffectHitTarget += SpellEffectFn(spell_najentus_needle_spine::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
void AddSC_boss_najentus()
{
- new boss_najentus();
- new go_najentus_spine();
- new spell_najentus_needle_spine();
+ RegisterBlackTempleCreatureAI(boss_najentus);
+ RegisterGameObjectAI(go_najentus_spine);
+ RegisterSpellScript(spell_najentus_needle_spine);
}
diff --git a/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp b/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp
index f679428e44e..3a4132ac8c7 100644
--- a/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp
+++ b/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp
@@ -101,7 +101,9 @@ class instance_black_temple : public InstanceMapScript
LoadDoorData(doorData);
LoadObjectData(creatureData, gameObjectData);
LoadBossBoundaries(boundaries);
- akamaState = AKAMA_INTRO;
+ AkamaState = AKAMA_INTRO;
+ TeronGorefiendIntro = 1;
+ AkamaIllidanIntro = 1;
}
void OnGameObjectCreate(GameObject* go) override
@@ -126,7 +128,7 @@ class instance_black_temple : public InstanceMapScript
case NPC_ASHTONGUE_STORMCALLER:
case NPC_ASHTONGUE_FERAL_SPIRIT:
case NPC_STORM_FURY:
- AshtongueGUIDs.emplace_back(creature->GetGUID());
+ AshtongueGUIDs.push_back(creature->GetGUID());
if (GetBossState(DATA_SHADE_OF_AKAMA) == DONE)
creature->SetFaction(FACTION_ASHTONGUE_DEATHSWORN);
break;
@@ -135,25 +137,37 @@ class instance_black_temple : public InstanceMapScript
}
}
- uint32 GetData(uint32 data) const override
+ uint32 GetData(uint32 type) const override
{
- if (data == DATA_AKAMA)
- return akamaState;
-
- return 0;
+ switch (type)
+ {
+ case DATA_AKAMA:
+ return AkamaState;
+ case DATA_TERON_GOREFIEND_INTRO:
+ return TeronGorefiendIntro;
+ case DATA_AKAMA_ILLIDAN_INTRO:
+ return AkamaIllidanIntro;
+ default:
+ return 0;
+ }
}
- void SetData(uint32 data, uint32 value) override
+ void SetData(uint32 type, uint32 data) override
{
- switch (data)
+ switch (type)
{
case DATA_AKAMA:
- akamaState = value;
+ AkamaState = data;
break;
case ACTION_OPEN_DOOR:
if (GameObject* illidanGate = GetGameObject(DATA_GO_ILLIDAN_GATE))
HandleGameObject(ObjectGuid::Empty, true, illidanGate);
break;
+ case DATA_TERON_GOREFIEND_INTRO:
+ TeronGorefiendIntro = data;
+ break;
+ case DATA_AKAMA_ILLIDAN_INTRO:
+ AkamaIllidanIntro = data;
default:
break;
}
@@ -211,7 +225,9 @@ class instance_black_temple : public InstanceMapScript
protected:
GuidVector AshtongueGUIDs;
- uint8 akamaState;
+ uint8 AkamaState;
+ uint8 TeronGorefiendIntro;
+ uint8 AkamaIllidanIntro;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp
index 29185f77185..2b0305f374a 100644
--- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp
+++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp
@@ -332,9 +332,7 @@ public:
if (instance->GetGuidData(DATA_LEOTHERAS_EVENT_STARTER))
{
- Unit* victim = nullptr;
- victim = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_LEOTHERAS_EVENT_STARTER));
- if (victim)
+ if (Unit* victim = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_LEOTHERAS_EVENT_STARTER)))
AddThreat(victim, 1);
StartEvent();
}
@@ -586,9 +584,7 @@ public:
//at this point he divides himself in two parts
CastConsumingMadness();
DespawnDemon();
- Creature* Copy = nullptr;
- Copy = DoSpawnCreature(DEMON_FORM, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 6000);
- if (Copy)
+ if (Creature* Copy = DoSpawnCreature(DEMON_FORM, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 6000))
{
Demon = Copy->GetGUID();
if (me->GetVictim())
@@ -738,7 +734,7 @@ public:
instance->SetGuidData(DATA_LEOTHERAS_EVENT_STARTER, who->GetGUID());
}
- void JustRespawned() override
+ void JustAppeared() override
{
AddedBanish = false;
Reset();
@@ -764,9 +760,7 @@ public:
if (!me->IsInCombat() && instance->GetGuidData(DATA_LEOTHERAS_EVENT_STARTER))
{
- Unit* victim = nullptr;
- victim = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_LEOTHERAS_EVENT_STARTER));
- if (victim)
+ if (Unit* victim = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_LEOTHERAS_EVENT_STARTER)))
AttackStart(victim);
}
@@ -784,10 +778,8 @@ public:
if (Mindblast_Timer <= diff)
{
- Unit* target = nullptr;
- target = SelectTarget(SELECT_TARGET_RANDOM, 0);
-
- if (target)DoCast(target, SPELL_MINDBLAST);
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ DoCast(target, SPELL_MINDBLAST);
Mindblast_Timer = urand(10000, 15000);
} else Mindblast_Timer -= diff;
diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp
index 4b694ab5861..0a26f129bf7 100644
--- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp
+++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp
@@ -148,7 +148,7 @@ class instance_serpent_shrine : public InstanceMapScript
player->CastSpell(player, SPELL_SCALDINGWATER, true);
}
- else if (Water == WATERSTATE_FRENZY)
+ else
{
//spawn frenzy
if (DoSpawnFrenzy)
diff --git a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp
index c5bb049d443..b7d7c10f6c7 100644
--- a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp
+++ b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp
@@ -308,7 +308,7 @@ public:
void Initialize()
{
me->SetReactState(REACT_PASSIVE);
- me->setRegeneratingHealth(false);
+ me->SetRegenerateHealth(false);
DoCast(me, SPELL_FROZEN_CORE_GETS_HIT);
DoCast(me, SPELL_ICE_SPEAR_AURA);
}
diff --git a/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp b/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp
index f6ad97f6328..ac6c9e62072 100644
--- a/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp
+++ b/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp
@@ -285,7 +285,7 @@ class spell_gruul_shatter : public SpellScriptLoader
if (Unit* target = GetHitUnit())
{
target->RemoveAurasDueToSpell(SPELL_STONED);
- target->CastSpell((Unit*)nullptr, SPELL_SHATTER_EFFECT, true);
+ target->CastSpell(nullptr, SPELL_SHATTER_EFFECT, true);
}
}
diff --git a/src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp b/src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp
index 57423f63ab0..2b43de82bb5 100644
--- a/src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp
+++ b/src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp
@@ -181,9 +181,7 @@ public:
//Charging_Timer
if (Charging_Timer <= diff)
{
- Unit* target = nullptr;
- target = SelectTarget(SELECT_TARGET_RANDOM, 0);
- if (target)
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
AttackStart(target);
DoCast(target, SPELL_BERSERKER_C);
@@ -293,9 +291,7 @@ public:
//DeathCoil Timer /need correct timer
if (DeathCoil_Timer <= diff)
{
- Unit* target = nullptr;
- target = SelectTarget(SELECT_TARGET_RANDOM, 0);
- if (target)
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
DoCast(target, SPELL_DEATH_COIL);
DeathCoil_Timer = 20000;
} else DeathCoil_Timer -= diff;
diff --git a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/boss_magtheridon.cpp b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/boss_magtheridon.cpp
index 354e4b0fce3..f0cf459acfe 100644
--- a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/boss_magtheridon.cpp
+++ b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/boss_magtheridon.cpp
@@ -477,9 +477,9 @@ public:
return true;
if (Creature* trigger = player->FindNearestCreature(NPC_HELFIRE_RAID_TRIGGER, 10.0f))
- trigger->CastSpell((Unit*)nullptr, SPELL_SHADOW_GRASP_VISUAL);
+ trigger->CastSpell(nullptr, SPELL_SHADOW_GRASP_VISUAL);
- player->CastSpell((Unit*)nullptr, SPELL_SHADOW_GRASP, true);
+ player->CastSpell(nullptr, SPELL_SHADOW_GRASP, true);
return true;
}
};
diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp
index 9b683770be0..6d65ceae758 100644
--- a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp
+++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp
@@ -436,9 +436,7 @@ class boss_alar : public CreatureScript
}
else
{
- Unit* target = nullptr;
- target = me->SelectNearestTargetInAttackDistance(5);
- if (target)
+ if (Unit* target = me->SelectNearestTargetInAttackDistance(5))
AttackStart(target);
else
{
diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp
index d3aa6b7e1fa..3323c53d546 100644
--- a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp
+++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp
@@ -1124,8 +1124,7 @@ class boss_grand_astromancer_capernian : public CreatureScript
//Conflagration_Timer
if (Conflagration_Timer <= diff)
{
- Unit* target = nullptr;
- target = SelectTarget(SELECT_TARGET_RANDOM, 0);
+ Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0);
if (target && me->IsWithinDistInMap(target, 30))
DoCast(target, SPELL_CONFLAGRATION);
diff --git a/src/server/scripts/Outland/boss_doomlord_kazzak.cpp b/src/server/scripts/Outland/boss_doomlord_kazzak.cpp
index 93ea132a545..240ec55c215 100644
--- a/src/server/scripts/Outland/boss_doomlord_kazzak.cpp
+++ b/src/server/scripts/Outland/boss_doomlord_kazzak.cpp
@@ -83,7 +83,7 @@ class boss_doomlord_kazzak : public CreatureScript
_events.ScheduleEvent(EVENT_BERSERK, 180000);
}
- void JustRespawned() override
+ void JustAppeared() override
{
Talk(SAY_INTRO);
}
diff --git a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp
index 0660d781e57..c56208d77af 100644
--- a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp
+++ b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp
@@ -150,9 +150,9 @@ class npc_ancestral_wolf : public CreatureScript
public:
npc_ancestral_wolf() : CreatureScript("npc_ancestral_wolf") { }
- struct npc_ancestral_wolfAI : public npc_escortAI
+ struct npc_ancestral_wolfAI : public EscortAI
{
- npc_ancestral_wolfAI(Creature* creature) : npc_escortAI(creature)
+ npc_ancestral_wolfAI(Creature* creature) : EscortAI(creature)
{
if (creature->GetOwner() && creature->GetOwner()->GetTypeId() == TYPEID_PLAYER)
Start(false, false, creature->GetOwner()->GetGUID());
@@ -170,11 +170,11 @@ public:
// Override Evade Mode event, recast buff that was removed by standard handler
void EnterEvadeMode(EvadeReason why) override
{
- npc_escortAI::EnterEvadeMode(why);
+ EscortAI::EnterEvadeMode(why);
DoCast(me, SPELL_ANCESTRAL_WOLF_BUFF, true);
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -258,9 +258,9 @@ class npc_wounded_blood_elf : public CreatureScript
public:
npc_wounded_blood_elf() : CreatureScript("npc_wounded_blood_elf") { }
- struct npc_wounded_blood_elfAI : public npc_escortAI
+ struct npc_wounded_blood_elfAI : public EscortAI
{
- npc_wounded_blood_elfAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_wounded_blood_elfAI(Creature* creature) : EscortAI(creature) { }
void Reset() override { }
@@ -280,11 +280,11 @@ public:
if (quest->GetQuestId() == QUEST_ROAD_TO_FALCON_WATCH)
{
me->SetFaction(FACTION_ESCORTEE_H_PASSIVE);
- npc_escortAI::Start(true, false, player->GetGUID());
+ EscortAI::Start(true, false, player->GetGUID());
}
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
diff --git a/src/server/scripts/Outland/zone_nagrand.cpp b/src/server/scripts/Outland/zone_nagrand.cpp
index ce71c80e5f0..d19e77a6d0f 100644
--- a/src/server/scripts/Outland/zone_nagrand.cpp
+++ b/src/server/scripts/Outland/zone_nagrand.cpp
@@ -73,9 +73,9 @@ class npc_maghar_captive : public CreatureScript
public:
npc_maghar_captive() : CreatureScript("npc_maghar_captive") { }
- struct npc_maghar_captiveAI : public npc_escortAI
+ struct npc_maghar_captiveAI : public EscortAI
{
- npc_maghar_captiveAI(Creature* creature) : npc_escortAI(creature) { Reset(); }
+ npc_maghar_captiveAI(Creature* creature) : EscortAI(creature) { Reset(); }
uint32 ChainLightningTimer;
uint32 HealTimer;
@@ -105,7 +105,7 @@ public:
}
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -157,7 +157,7 @@ public:
void UpdateAI(uint32 diff) override
{
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (!UpdateVictim())
return;
@@ -434,9 +434,9 @@ class npc_kurenai_captive : public CreatureScript
public:
npc_kurenai_captive() : CreatureScript("npc_kurenai_captive") { }
- struct npc_kurenai_captiveAI : public npc_escortAI
+ struct npc_kurenai_captiveAI : public EscortAI
{
- npc_kurenai_captiveAI(Creature* creature) : npc_escortAI(creature)
+ npc_kurenai_captiveAI(Creature* creature) : EscortAI(creature)
{
Initialize();
}
@@ -474,7 +474,7 @@ public:
}
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
switch (waypointId)
{
@@ -538,7 +538,7 @@ public:
void UpdateAI(uint32 diff) override
{
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
if (!UpdateVictim())
return;
diff --git a/src/server/scripts/Outland/zone_netherstorm.cpp b/src/server/scripts/Outland/zone_netherstorm.cpp
index 6fcf5c37004..8104282117c 100644
--- a/src/server/scripts/Outland/zone_netherstorm.cpp
+++ b/src/server/scripts/Outland/zone_netherstorm.cpp
@@ -488,9 +488,9 @@ class npc_bessy : public CreatureScript
public:
npc_bessy() : CreatureScript("npc_bessy") { }
- struct npc_bessyAI : public npc_escortAI
+ struct npc_bessyAI : public EscortAI
{
- npc_bessyAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_bessyAI(Creature* creature) : EscortAI(creature) { }
void JustDied(Unit* /*killer*/) override
{
@@ -498,7 +498,7 @@ public:
player->FailQuest(Q_ALMABTRIEB);
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
@@ -569,9 +569,9 @@ class npc_maxx_a_million_escort : public CreatureScript
public:
npc_maxx_a_million_escort() : CreatureScript("npc_maxx_a_million_escort") { }
- struct npc_maxx_a_million_escortAI : public npc_escortAI
+ struct npc_maxx_a_million_escortAI : public EscortAI
{
- npc_maxx_a_million_escortAI(Creature* creature) : npc_escortAI(creature)
+ npc_maxx_a_million_escortAI(Creature* creature) : EscortAI(creature)
{
Initialize();
}
@@ -590,7 +590,7 @@ public:
Initialize();
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
@@ -624,7 +624,7 @@ public:
void UpdateAI(uint32 uiDiff) override
{
- npc_escortAI::UpdateAI(uiDiff);
+ EscortAI::UpdateAI(uiDiff);
if (bTake)
{
@@ -668,7 +668,11 @@ public:
enum CaptainTyralius
{
NPC_CAPTAIN_TYRALIUS = 20787,
+ NPC_ETHEREUM_PRISONER = 20825,
+ SPELL_TELEPORT_VISUAL = 51347,
SAY_FREE = 0,
+ ACTION_FREED = 0,
+ EVENT_TELEPORT = 1
};
class go_captain_tyralius_prison : public GameObjectScript
@@ -680,15 +684,26 @@ class go_captain_tyralius_prison : public GameObjectScript
{
go_captain_tyralius_prisonAI(GameObject* go) : GameObjectAI(go) { }
+ void Reset() override
+ {
+ me->SummonCreature(NPC_CAPTAIN_TYRALIUS, me->GetPosition(), TEMPSUMMON_MANUAL_DESPAWN);
+ me->SummonCreature(NPC_ETHEREUM_PRISONER, me->GetPosition(), TEMPSUMMON_MANUAL_DESPAWN);
+ }
+
bool GossipHello(Player* player) override
{
- me->UseDoorOrButton();
+ me->SetRespawnTime(60);
+ me->SetLootState(GO_JUST_DEACTIVATED);
+
if (Creature* tyralius = me->FindNearestCreature(NPC_CAPTAIN_TYRALIUS, 1.0f))
{
player->KilledMonsterCredit(NPC_CAPTAIN_TYRALIUS);
- tyralius->AI()->Talk(SAY_FREE);
- tyralius->DespawnOrUnsummon(8000);
+ tyralius->AI()->DoAction(ACTION_FREED);
}
+
+ if (Creature* prisoner = me->FindNearestCreature(NPC_ETHEREUM_PRISONER, 1.0f))
+ prisoner->DespawnOrUnsummon(0);
+
return true;
}
};
@@ -699,6 +714,47 @@ class go_captain_tyralius_prison : public GameObjectScript
}
};
+class npc_captain_tyralius : public CreatureScript
+{
+public:
+ npc_captain_tyralius() : CreatureScript("npc_captain_tyralius") { }
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return new npc_captain_tyraliusAI(creature);
+ }
+
+ struct npc_captain_tyraliusAI : public ScriptedAI
+ {
+ npc_captain_tyraliusAI(Creature* creature) : ScriptedAI(creature) { }
+
+ void DoAction(int32 /*action*/) override
+ {
+ Talk(SAY_FREE);
+ _events.ScheduleEvent(EVENT_TELEPORT, Seconds(5));
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
+
+ if (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_TELEPORT:
+ DoCastSelf(SPELL_TELEPORT_VISUAL);
+ me->DespawnOrUnsummon(Seconds(2));
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap _events;
+ };
+};
+
void AddSC_netherstorm()
{
new npc_commander_dawnforge();
@@ -707,4 +763,5 @@ void AddSC_netherstorm()
new npc_bessy();
new npc_maxx_a_million_escort();
new go_captain_tyralius_prison();
+ new npc_captain_tyralius();
}
diff --git a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp
index 65eaefa2d7b..9ee82504a49 100644
--- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp
+++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp
@@ -592,9 +592,9 @@ class npc_earthmender_wilda : public CreatureScript
public:
npc_earthmender_wilda() : CreatureScript("npc_earthmender_wilda") { }
- struct npc_earthmender_wildaAI : public npc_escortAI
+ struct npc_earthmender_wildaAI : public EscortAI
{
- npc_earthmender_wildaAI(Creature* creature) : npc_escortAI(creature)
+ npc_earthmender_wildaAI(Creature* creature) : EscortAI(creature)
{
Initialize();
}
@@ -611,7 +611,7 @@ public:
Initialize();
}
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
@@ -704,7 +704,7 @@ public:
void UpdateAI(uint32 uiDiff) override
{
- npc_escortAI::UpdateAI(uiDiff);
+ EscortAI::UpdateAI(uiDiff);
if (!UpdateVictim())
return;
@@ -1376,7 +1376,7 @@ public:
enum Enraged_Dpirits
{
-// QUESTS
+ // QUESTS
QUEST_ENRAGED_SPIRITS_FIRE_EARTH = 10458,
QUEST_ENRAGED_SPIRITS_AIR = 10481,
QUEST_ENRAGED_SPIRITS_WATER = 10480,
@@ -1391,6 +1391,22 @@ enum Enraged_Dpirits
NPC_ENRAGED_AIR_SPIRIT = 21060,
NPC_ENRAGED_WATER_SPIRIT = 21059,
+ // ENRAGED WATER SPIRIT SPELLS
+ SPELL_STORMBOLT = 38032,
+
+ // ENRAGED AIR SPIRIT SPELLS
+ SPELL_AIR_SPIRIT_CHAIN_LIGHTNING = 12058,
+ SPELL_HURRICANE = 32717,
+ SPELL_ENRAGE = 8599,
+
+ // ENRAGED FIRE SPIRIT SPELLS - Will be using the enrage spell from Air Spirit
+ SPELL_FEL_FIREBALL = 36247,
+ SPELL_FEL_FIRE_AURA = 36006, // Earth spirit uses this one
+
+ // ENRAGED EARTH SPIRIT SPELLS
+ SPELL_FIERY_BOULDER = 38498,
+ SPELL_SUMMON_ENRAGED_EARTH_SHARD = 38365,
+
// SOULS
NPC_EARTHEN_SOUL = 21073,
NPC_FIERY_SOUL = 21097,
@@ -1413,6 +1429,15 @@ enum Enraged_Dpirits
SPELL_SOUL_CAPTURED = 36115
};
+enum Enraged_Spirits_Events
+{
+ EVENT_ENRAGED_WATER_SPIRIT = 1,
+ EVENT_ENRAGED_FIRE_SPIRIT = 2,
+ EVENT_ENRAGED_EARTH_SPIRIT = 3,
+ EVENT_ENRAGED_AIR_SPIRIT_CHAIN_LIGHTNING = 4,
+ EVENT_ENRAGED_AIR_SPIRIT_HURRICANE = 5
+};
+
class npc_enraged_spirit : public CreatureScript
{
public:
@@ -1420,7 +1445,7 @@ public:
CreatureAI* GetAI(Creature* creature) const override
{
- return new npc_enraged_spiritAI(creature);
+ return new npc_enraged_spiritAI(creature);
}
struct npc_enraged_spiritAI : public ScriptedAI
@@ -1429,7 +1454,77 @@ public:
void Reset() override { }
- void EnterCombat(Unit* /*who*/) override { }
+ void EnterCombat(Unit* /*who*/) override
+ {
+ switch (me->GetEntry())
+ {
+ case NPC_ENRAGED_WATER_SPIRIT:
+ _events.ScheduleEvent(EVENT_ENRAGED_WATER_SPIRIT, Seconds(0), Seconds(1));
+ break;
+ case NPC_ENRAGED_FIRE_SPIRIT:
+ if (!me->GetAura(SPELL_FEL_FIRE_AURA))
+ DoCastSelf(SPELL_FEL_FIRE_AURA);
+ _events.ScheduleEvent(EVENT_ENRAGED_FIRE_SPIRIT, Seconds(2), Seconds(10));
+ break;
+ case NPC_ENRAGED_EARTH_SPIRIT:
+ if (!me->GetAura(SPELL_FEL_FIRE_AURA))
+ DoCastSelf(SPELL_FEL_FIRE_AURA);
+ _events.ScheduleEvent(EVENT_ENRAGED_EARTH_SPIRIT, Seconds(3), Seconds(4));
+ break;
+ case NPC_ENRAGED_AIR_SPIRIT:
+ _events.ScheduleEvent(EVENT_ENRAGED_AIR_SPIRIT_CHAIN_LIGHTNING, Seconds(10));
+ break;
+ default:
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_ENRAGED_WATER_SPIRIT:
+ if (UpdateVictim())
+ DoCastVictim(SPELL_STORMBOLT);
+ _events.Repeat(Seconds(17), Seconds(23));
+ break;
+ case EVENT_ENRAGED_FIRE_SPIRIT:
+ if (UpdateVictim())
+ DoCastVictim(SPELL_FEL_FIREBALL);
+ _events.Repeat(Seconds(6), Seconds(12));
+ break;
+ case EVENT_ENRAGED_EARTH_SPIRIT:
+ if (UpdateVictim())
+ DoCastVictim(SPELL_FIERY_BOULDER);
+ _events.Repeat(Seconds(6), Seconds(9));
+ break;
+ case EVENT_ENRAGED_AIR_SPIRIT_CHAIN_LIGHTNING:
+ if (UpdateVictim())
+ DoCastVictim(SPELL_CHAIN_LIGHTNING);
+ _events.ScheduleEvent(EVENT_ENRAGED_AIR_SPIRIT_HURRICANE, Seconds(3), Seconds(5));
+ break;
+ case EVENT_ENRAGED_AIR_SPIRIT_HURRICANE:
+ if (UpdateVictim())
+ DoCastVictim(SPELL_HURRICANE);
+ _events.ScheduleEvent(EVENT_ENRAGED_AIR_SPIRIT_CHAIN_LIGHTNING, Seconds(15), Seconds(20));
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (me->GetEntry() == NPC_ENRAGED_FIRE_SPIRIT || me->GetEntry() == NPC_ENRAGED_AIR_SPIRIT)
+ if (HealthBelowPct(35) && !me->GetAura(SPELL_ENRAGE))
+ DoCastSelf(SPELL_ENRAGE);
+
+ DoMeleeAttackIfReady();
+ }
void JustDied(Unit* /*killer*/) override
{
@@ -1450,6 +1545,7 @@ public:
entry = NPC_EARTHEN_SOUL;
//credit = SPELL_EARTHEN_SOUL_CAPTURED_CREDIT;
credit = NPC_CREDIT_EARTH;
+ DoCastSelf(SPELL_SUMMON_ENRAGED_EARTH_SHARD);
break;
case NPC_ENRAGED_AIR_SPIRIT:
entry = NPC_ENRAGED_AIRY_SOUL;
@@ -1488,6 +1584,9 @@ public:
}
}
}
+
+ private:
+ EventMap _events;
};
};
diff --git a/src/server/scripts/Outland/zone_shattrath_city.cpp b/src/server/scripts/Outland/zone_shattrath_city.cpp
index 87143a32e7b..073897b5689 100644
--- a/src/server/scripts/Outland/zone_shattrath_city.cpp
+++ b/src/server/scripts/Outland/zone_shattrath_city.cpp
@@ -19,346 +19,21 @@
/* ScriptData
SDName: Shattrath_City
SD%Complete: 100
-SDComment: Quest support: 10004, 10009, 10211. Flask vendors, Teleport to Caverns of Time
+SDComment: Quest support: 10211.
SDCategory: Shattrath City
EndScriptData */
/* ContentData
-npc_raliq_the_drunk
-npc_salsalabim
-npc_shattrathflaskvendors
-npc_zephyr
npc_kservant
EndContentData */
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
-#include "ScriptedGossip.h"
#include "ScriptedEscortAI.h"
#include "Player.h"
#include "WorldSession.h"
/*######
-## npc_raliq_the_drunk
-######*/
-
-enum RaliqTheDrunk
-{
- SAY_RALIQ_ATTACK = 0,
- OPTION_ID_COLLECT_A_DEBT = 0,
- MENU_ID_COLLECT_A_DEBT = 7729,
- NPC_TEXT_WUT_YOU_WANT = 9440,
- CRACKIN_SOME_SKULLS = 10009,
- SPELL_UPPERCUT = 10966
-};
-
-class npc_raliq_the_drunk : public CreatureScript
-{
-public:
- npc_raliq_the_drunk() : CreatureScript("npc_raliq_the_drunk") { }
-
- struct npc_raliq_the_drunkAI : public ScriptedAI
- {
- npc_raliq_the_drunkAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- }
-
- void Initialize()
- {
- Uppercut_Timer = 5000;
- }
-
- uint32 Uppercut_Timer;
-
- void Reset() override
- {
- Initialize();
- me->RestoreFaction();
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
-
- if (Uppercut_Timer <= diff)
- {
- DoCastVictim(SPELL_UPPERCUT);
- Uppercut_Timer = 15000;
- } else Uppercut_Timer -= diff;
-
- DoMeleeAttackIfReady();
- }
-
- bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
- {
- uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
- ClearGossipMenuFor(player);
- if (action == GOSSIP_ACTION_INFO_DEF + 1)
- {
- CloseGossipMenuFor(player);
- me->SetFaction(FACTION_OGRE);
- Talk(SAY_RALIQ_ATTACK, player);
- AttackStart(player);
- }
- return true;
- }
-
- bool GossipHello(Player* player) override
- {
- if (player->GetQuestStatus(CRACKIN_SOME_SKULLS) == QUEST_STATUS_INCOMPLETE)
- {
- AddGossipItemFor(player, MENU_ID_COLLECT_A_DEBT, OPTION_ID_COLLECT_A_DEBT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- SendGossipMenuFor(player, NPC_TEXT_WUT_YOU_WANT, me->GetGUID());
- }
- else
- {
- ClearGossipMenuFor(player);
- SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
- }
- return true;
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_raliq_the_drunkAI(creature);
- }
-};
-
-/*######
-# npc_salsalabim
-######*/
-
-enum Salsalabim
-{
- SAY_DEMONIC_AGGRO = 0,
- OPTION_ID_ALTRUIS_SENT_ME = 0,
- MENU_ID_ALTRUIS_SENT_ME = 7725,
- NPC_TEXT_SAL_GROWLS_AT_YOU = 9435,
- PATIENCE_AND_UNDERSTANDING = 10004,
- SPELL_MAGNETIC_PULL = 31705
-};
-
-class npc_salsalabim : public CreatureScript
-{
-public:
- npc_salsalabim() : CreatureScript("npc_salsalabim") { }
-
- struct npc_salsalabimAI : public ScriptedAI
- {
- npc_salsalabimAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- }
-
- void Initialize()
- {
- MagneticPull_Timer = 15000;
- }
-
- uint32 MagneticPull_Timer;
-
- void Reset() override
- {
- Initialize();
- me->RestoreFaction();
- }
-
- void DamageTaken(Unit* done_by, uint32 &damage) override
- {
- if (done_by->GetTypeId() == TYPEID_PLAYER && me->HealthBelowPctDamaged(20, damage))
- {
- done_by->ToPlayer()->GroupEventHappens(PATIENCE_AND_UNDERSTANDING, me);
- damage = 0;
- EnterEvadeMode();
- }
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
-
- if (MagneticPull_Timer <= diff)
- {
- DoCastVictim(SPELL_MAGNETIC_PULL);
- MagneticPull_Timer = 15000;
- } else MagneticPull_Timer -= diff;
-
- DoMeleeAttackIfReady();
- }
-
- bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
- {
- uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
- ClearGossipMenuFor(player);
- if (action == GOSSIP_ACTION_INFO_DEF + 1)
- {
- CloseGossipMenuFor(player);
- me->SetFaction(FACTION_DEMON);
- Talk(SAY_DEMONIC_AGGRO, player);
- AttackStart(player);
- }
- return true;
- }
-
- bool GossipHello(Player* player) override
- {
- if (player->GetQuestStatus(PATIENCE_AND_UNDERSTANDING) == QUEST_STATUS_INCOMPLETE)
- {
- AddGossipItemFor(player, MENU_ID_ALTRUIS_SENT_ME, OPTION_ID_ALTRUIS_SENT_ME, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- SendGossipMenuFor(player, NPC_TEXT_SAL_GROWLS_AT_YOU, me->GetGUID());
- }
- else
- {
- if (me->IsQuestGiver())
- player->PrepareQuestMenu(me->GetGUID());
- SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
- }
- return true;
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_salsalabimAI(creature);
- }
-};
-
-/*
-##################################################
-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
-##################################################
-*/
-
-enum FlaskVendors
-{
- ALDOR_REPUTATION = 932,
- SCRYERS_REPUTATION = 934,
- THE_SHA_TAR_REPUTATION = 935,
- CENARION_EXPEDITION_REP = 942,
- NPC_TEXT_EXALTED_ALDOR = 11083, // (need to be exalted with Sha'tar, Cenarion Expedition and the Aldor)
- NPC_TEXT_EXALTED_SCRYERS = 11084, // (need to be exalted with Sha'tar, Cenarion Expedition and the Scryers)
- NPC_TEXT_WELCOME_NAME = 11085, // Access granted
- ARCANIST_XORITH = 23483, // Scryer Apothecary
- HALDOR_THE_COMPULSIVE = 23484 // Aldor Apothecary
-};
-
-class npc_shattrathflaskvendors : public CreatureScript
-{
-public:
- npc_shattrathflaskvendors() : CreatureScript("npc_shattrathflaskvendors") { }
-
- struct npc_shattrathflaskvendorsAI : public ScriptedAI
- {
- npc_shattrathflaskvendorsAI(Creature* creature) : ScriptedAI(creature) { }
-
- bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
- {
- uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
- ClearGossipMenuFor(player);
- if (action == GOSSIP_ACTION_TRADE)
- player->GetSession()->SendListInventory(me->GetGUID());
-
- return true;
- }
-
- bool GossipHello(Player* player) override
- {
- if (me->GetEntry() == HALDOR_THE_COMPULSIVE)
- {
- // Aldor vendor
- if (me->IsVendor() && (player->GetReputationRank(ALDOR_REPUTATION) == REP_EXALTED) && (player->GetReputationRank(THE_SHA_TAR_REPUTATION) == REP_EXALTED) && (player->GetReputationRank(CENARION_EXPEDITION_REP) == REP_EXALTED))
- {
- AddGossipItemFor(player, GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
- SendGossipMenuFor(player, NPC_TEXT_WELCOME_NAME, me->GetGUID());
- }
- else
- {
- SendGossipMenuFor(player, NPC_TEXT_EXALTED_ALDOR, me->GetGUID());
- }
- }
-
- if (me->GetEntry() == ARCANIST_XORITH)
- {
- // Scryers vendor
- if (me->IsVendor() && (player->GetReputationRank(SCRYERS_REPUTATION) == REP_EXALTED) && (player->GetReputationRank(THE_SHA_TAR_REPUTATION) == REP_EXALTED) && (player->GetReputationRank(CENARION_EXPEDITION_REP) == REP_EXALTED))
- {
- AddGossipItemFor(player, GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
- SendGossipMenuFor(player, NPC_TEXT_WELCOME_NAME, me->GetGUID());
- }
- else
- {
- SendGossipMenuFor(player, NPC_TEXT_EXALTED_SCRYERS, me->GetGUID());
- }
- }
-
- return true;
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_shattrathflaskvendorsAI(creature);
- }
-};
-
-/*######
-# npc_zephyr
-######*/
-
-enum Zephyr
-{
- OPTION_ID_TAKE_ME_TO_C_O_T = 0,
- KEEPERS_OF_TIME_REPUTATION = 989,
- MENU_ID_TAKE_ME_TO_C_O_T = 9205,
- TELEPORT_CAVERNS_OF_TIME = 37778
-};
-
-class npc_zephyr : public CreatureScript
-{
-public:
- npc_zephyr() : CreatureScript("npc_zephyr") { }
-
- struct npc_zephyrAI : public ScriptedAI
- {
- npc_zephyrAI(Creature* creature) : ScriptedAI(creature) { }
-
- bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
- {
- uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
- ClearGossipMenuFor(player);
- if (action == GOSSIP_ACTION_INFO_DEF + 1)
- player->CastSpell(player, TELEPORT_CAVERNS_OF_TIME, false);
-
- return true;
- }
-
- bool GossipHello(Player* player) override
- {
- if (player->GetReputationRank(KEEPERS_OF_TIME_REPUTATION) >= REP_REVERED)
- AddGossipItemFor(player, MENU_ID_TAKE_ME_TO_C_O_T, OPTION_ID_TAKE_ME_TO_C_O_T, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
-
- SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
-
- return true;
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_zephyrAI(creature);
- }
-};
-
-/*######
# npc_kservant
######*/
@@ -399,12 +74,12 @@ public:
return new npc_kservantAI(creature);
}
- struct npc_kservantAI : public npc_escortAI
+ struct npc_kservantAI : public EscortAI
{
public:
- npc_kservantAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_kservantAI(Creature* creature) : EscortAI(creature) { }
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
@@ -505,9 +180,5 @@ public:
void AddSC_shattrath_city()
{
- new npc_raliq_the_drunk();
- new npc_salsalabim();
- new npc_shattrathflaskvendors();
- new npc_zephyr();
new npc_kservant();
}
diff --git a/src/server/scripts/Outland/zone_terokkar_forest.cpp b/src/server/scripts/Outland/zone_terokkar_forest.cpp
index 758db799ea4..a8b91b913e5 100644
--- a/src/server/scripts/Outland/zone_terokkar_forest.cpp
+++ b/src/server/scripts/Outland/zone_terokkar_forest.cpp
@@ -19,26 +19,22 @@
/* ScriptData
SDName: Terokkar_Forest
SD%Complete: 85
-SDComment: Quest support: 9889, 10009, 10873, 10896, 10898, 11096, 10052, 10051. Skettis->Ogri'la Flight
+SDComment: Quest support: 9889, 10898, 10052, 10051.
SDCategory: Terokkar Forest
EndScriptData */
/* ContentData
npc_unkor_the_ruthless
-npc_infested_root_walker
-npc_rotting_forest_rager
-npc_floon
npc_isla_starmane
-npc_slim
+npc_skywing
+npc_akuno
EndContentData */
#include "ScriptMgr.h"
#include "GameObject.h"
-#include "GameObjectAI.h"
#include "Group.h"
#include "Player.h"
#include "ScriptedEscortAI.h"
-#include "ScriptedGossip.h"
#include "WorldSession.h"
/*######
@@ -166,43 +162,6 @@ public:
};
/*######
-## npc_infested_root_walker
-######*/
-
-enum InfestedRootWalker
-{
- SPELL_SUMMON_WOOD_MITES = 39130
-};
-
-class npc_infested_root_walker : public CreatureScript
-{
-public:
- npc_infested_root_walker() : CreatureScript("npc_infested_root_walker") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_infested_root_walkerAI(creature);
- }
-
- struct npc_infested_root_walkerAI : public ScriptedAI
- {
- npc_infested_root_walkerAI(Creature* creature) : ScriptedAI(creature) { }
-
- void Reset() override { }
- void EnterCombat(Unit* /*who*/) override { }
-
- void DamageTaken(Unit* done_by, uint32 &damage) override
- {
- if (done_by && done_by->GetTypeId() == TYPEID_PLAYER)
- if (me->GetHealth() <= damage)
- if (rand32() % 100 < 75)
- //Summon Wood Mites
- DoCast(me, SPELL_SUMMON_WOOD_MITES, true);
- }
- };
-};
-
-/*######
## npc_skywing
######*/
@@ -221,12 +180,12 @@ public:
return new npc_skywingAI(creature);
}
- struct npc_skywingAI : public npc_escortAI
+ struct npc_skywingAI : public EscortAI
{
public:
- npc_skywingAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_skywingAI(Creature* creature) : EscortAI(creature) { }
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
@@ -258,162 +217,9 @@ public:
void UpdateAI(uint32 diff) override
{
- npc_escortAI::UpdateAI(diff);
- }
- };
-};
-
-/*######
-## npc_rotting_forest_rager
-######*/
-
-enum RottingForestRager
-{
- SPELL_SUMMON_LOTS_OF_WOOD_MITES = 39134
-};
-
-class npc_rotting_forest_rager : public CreatureScript
-{
-public:
- npc_rotting_forest_rager() : CreatureScript("npc_rotting_forest_rager") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_rotting_forest_ragerAI(creature);
- }
-
- struct npc_rotting_forest_ragerAI : public ScriptedAI
- {
- npc_rotting_forest_ragerAI(Creature* creature) : ScriptedAI(creature) { }
-
- void Reset() override { }
- void EnterCombat(Unit* /*who*/) override { }
-
- void DamageTaken(Unit* done_by, uint32 &damage) override
- {
- if (done_by->GetTypeId() == TYPEID_PLAYER)
- if (me->GetHealth() <= damage)
- if (rand32() % 100 < 75)
- //Summon Lots of Wood Mites
- DoCast(me, SPELL_SUMMON_LOTS_OF_WOOD_MITES, true);
- }
- };
-};
-
-/*######
-## npc_floon
-######*/
-
-enum Floon
-{
- SAY_FLOON_ATTACK = 0,
- OPTION_ID_PAY_UP_OR_DIE = 0,
- OPTION_ID_COLLECT_A_DEBT = 0,
- MENU_ID_PAY_UP_OR_DIE = 7731,
- MENU_ID_COLLECT_A_DEBT = 7732,
- GOSSIP_FLOON_STRANGE_SOUNDS = 9442,
- GOSSIP_HE_ALREADY_KILLED_ME = 9443,
-
- SPELL_SILENCE = 6726,
- SPELL_FROSTBOLT = 9672,
- SPELL_FROST_NOVA = 11831,
-
- QUEST_CRACKIN_SOME_SKULLS = 10009
-};
-
-class npc_floon : public CreatureScript
-{
-public:
- npc_floon() : CreatureScript("npc_floon") { }
-
- struct npc_floonAI : public ScriptedAI
- {
- npc_floonAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- m_uiNormFaction = creature->GetFaction();
- }
-
- void Initialize()
- {
- Silence_Timer = 2000;
- Frostbolt_Timer = 4000;
- FrostNova_Timer = 9000;
- }
-
- uint32 m_uiNormFaction;
- uint32 Silence_Timer;
- uint32 Frostbolt_Timer;
- uint32 FrostNova_Timer;
-
- void Reset() override
- {
- Initialize();
- if (me->GetFaction() != m_uiNormFaction)
- me->SetFaction(m_uiNormFaction);
- }
-
- void EnterCombat(Unit* /*who*/) override { }
-
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
-
- if (Silence_Timer <= diff)
- {
- DoCastVictim(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)
- {
- DoCastVictim(SPELL_FROSTBOLT);
- Frostbolt_Timer = 5000;
- } else Frostbolt_Timer -= diff;
-
- DoMeleeAttackIfReady();
- }
-
- bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
- {
- uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
- ClearGossipMenuFor(player);
- if (action == GOSSIP_ACTION_INFO_DEF)
- {
- AddGossipItemFor(player, MENU_ID_PAY_UP_OR_DIE, OPTION_ID_PAY_UP_OR_DIE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- SendGossipMenuFor(player, GOSSIP_HE_ALREADY_KILLED_ME, me->GetGUID());
- }
- if (action == GOSSIP_ACTION_INFO_DEF + 1)
- {
- CloseGossipMenuFor(player);
- me->SetFaction(FACTION_ARAKKOA);
- Talk(SAY_FLOON_ATTACK, player);
- AttackStart(player);
- }
- return true;
- }
-
- bool GossipHello(Player* player) override
- {
- if (player->GetQuestStatus(QUEST_CRACKIN_SOME_SKULLS) == QUEST_STATUS_INCOMPLETE)
- AddGossipItemFor(player, MENU_ID_COLLECT_A_DEBT, OPTION_ID_COLLECT_A_DEBT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
-
- SendGossipMenuFor(player, GOSSIP_FLOON_STRANGE_SOUNDS, me->GetGUID());
- return true;
+ EscortAI::UpdateAI(diff);
}
};
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_floonAI(creature);
- }
};
/*######
@@ -437,11 +243,11 @@ class npc_isla_starmane : public CreatureScript
public:
npc_isla_starmane() : CreatureScript("npc_isla_starmane") { }
- struct npc_isla_starmaneAI : public npc_escortAI
+ struct npc_isla_starmaneAI : public EscortAI
{
- npc_isla_starmaneAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_isla_starmaneAI(Creature* creature) : EscortAI(creature) { }
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
@@ -512,135 +318,6 @@ public:
}
};
-/*######
-## go_skull_pile
-######*/
-
-enum SkullPile
-{
- OPTION_ID_GEZZARAK_THE_HUNTRESS = 0,
- OPTION_ID_DARKSCREECHER_AKKARAI = 1,
- OPTION_ID_KARROG = 2,
- OPTION_ID_VAKKIZ_THE_WINDRAGER = 3,
- GOSSIP_MENU_ID_SKULL_PILE = 8660,
- ADVERSARIAL_BLOOD = 11885,
- SUMMON_GEZZARAK_THE_HUNTRESS = 40632,
- SUMMON_KARROG = 40640,
- SUMMON_DARKSCREECHER_AKKARAI = 40642,
- SUMMON_VAKKIZ_THE_WINDRAGER = 40644
-};
-
-class go_skull_pile : public GameObjectScript
-{
-public:
- go_skull_pile() : GameObjectScript("go_skull_pile") { }
-
- struct go_skull_pileAI : public GameObjectAI
- {
- go_skull_pileAI(GameObject* go) : GameObjectAI(go) { }
-
- bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
- {
- uint32 const sender = player->PlayerTalkClass->GetGossipOptionSender(gossipListId);
- uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
- ClearGossipMenuFor(player);
- switch (sender)
- {
- case GOSSIP_SENDER_MAIN: SendActionMenu(player, action); break;
- }
- return true;
- }
-
- bool GossipHello(Player* player) override
- {
- if ((player->GetQuestStatus(ADVERSARIAL_BLOOD) == QUEST_STATUS_INCOMPLETE) || player->GetQuestRewardStatus(ADVERSARIAL_BLOOD))
- {
- AddGossipItemFor(player, GOSSIP_MENU_ID_SKULL_PILE, OPTION_ID_GEZZARAK_THE_HUNTRESS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- AddGossipItemFor(player, GOSSIP_MENU_ID_SKULL_PILE, OPTION_ID_DARKSCREECHER_AKKARAI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
- AddGossipItemFor(player, GOSSIP_MENU_ID_SKULL_PILE, OPTION_ID_KARROG, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
- AddGossipItemFor(player, GOSSIP_MENU_ID_SKULL_PILE, OPTION_ID_VAKKIZ_THE_WINDRAGER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
- }
-
- SendGossipMenuFor(player, me->GetGOInfo()->questgiver.gossipID, me->GetGUID());
- return true;
- }
-
- void SendActionMenu(Player* player, uint32 action)
- {
- switch (action)
- {
- case GOSSIP_ACTION_INFO_DEF + 1:
- player->CastSpell(player, SUMMON_GEZZARAK_THE_HUNTRESS, false);
- break;
- case GOSSIP_ACTION_INFO_DEF + 2:
- player->CastSpell(player, SUMMON_DARKSCREECHER_AKKARAI, false);
- break;
- case GOSSIP_ACTION_INFO_DEF + 3:
- player->CastSpell(player, SUMMON_KARROG, false);
- break;
- case GOSSIP_ACTION_INFO_DEF + 4:
- player->CastSpell(player, SUMMON_VAKKIZ_THE_WINDRAGER, false);
- break;
- }
- }
- };
-
- GameObjectAI* GetAI(GameObject* go) const override
- {
- return new go_skull_pileAI(go);
- }
-};
-
-/*######
-## npc_slim
-######*/
-
-enum Slim
-{
- FACTION_CONSORTIUM = 933,
- NPC_TEXT_NEITHER_SLIM_NOR_SHADY = 9895,
- NPC_TEXT_I_SEE_YOU_ARE_A_FRIEND = 9896
-};
-
-class npc_slim : public CreatureScript
-{
-public:
- npc_slim() : CreatureScript("npc_slim") { }
-
- struct npc_slimAI : public ScriptedAI
- {
- npc_slimAI(Creature* creature) : ScriptedAI(creature) { }
-
- bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
- {
- uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
- ClearGossipMenuFor(player);
- if (action == GOSSIP_ACTION_TRADE)
- player->GetSession()->SendListInventory(me->GetGUID());
-
- return true;
- }
-
- bool GossipHello(Player* player) override
- {
- if (me->IsVendor() && player->GetReputationRank(FACTION_CONSORTIUM) >= REP_FRIENDLY)
- {
- AddGossipItemFor(player, GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
- SendGossipMenuFor(player, NPC_TEXT_I_SEE_YOU_ARE_A_FRIEND, me->GetGUID());
- }
- else
- SendGossipMenuFor(player, NPC_TEXT_NEITHER_SLIM_NOR_SHADY, me->GetGUID());
-
- return true;
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_slimAI(creature);
- }
-};
-
/*########
####npc_akuno
#####*/
@@ -656,11 +333,11 @@ class npc_akuno : public CreatureScript
public:
npc_akuno() : CreatureScript("npc_akuno") { }
- struct npc_akunoAI : public npc_escortAI
+ struct npc_akunoAI : public EscortAI
{
- npc_akunoAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_akunoAI(Creature* creature) : EscortAI(creature) { }
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
@@ -707,12 +384,7 @@ public:
void AddSC_terokkar_forest()
{
new npc_unkor_the_ruthless();
- new npc_infested_root_walker();
- new npc_rotting_forest_rager();
- new npc_floon();
new npc_isla_starmane();
- new go_skull_pile();
new npc_skywing();
- new npc_slim();
new npc_akuno();
}
diff --git a/src/server/scripts/Outland/zone_zangarmarsh.cpp b/src/server/scripts/Outland/zone_zangarmarsh.cpp
index fabf7290129..9eff40f296c 100644
--- a/src/server/scripts/Outland/zone_zangarmarsh.cpp
+++ b/src/server/scripts/Outland/zone_zangarmarsh.cpp
@@ -19,14 +19,12 @@
/* ScriptData
SDName: Zangarmarsh
SD%Complete: 100
-SDComment: Quest support: 9752, 9785, 9803, 10009. Mark Of ... buffs.
+SDComment: Quest support: 9752, 9785, Mark Of ... buffs.
SDCategory: Zangarmarsh
EndScriptData */
/* ContentData
npcs_ashyen_and_keleth
-npc_cooshcoosh
-npc_elder_kuruti
npc_kayra_longmane
EndContentData */
@@ -157,159 +155,6 @@ public:
};
/*######
-## npc_cooshcoosh
-######*/
-
-#define GOSSIP_COOSH "You owe Sim'salabim money. Hand them over or die!"
-
-enum Cooshhooosh
-{
- SPELL_LIGHTNING_BOLT = 9532,
- QUEST_CRACK_SKULLS = 10009
-};
-
-class npc_cooshcoosh : public CreatureScript
-{
-public:
- npc_cooshcoosh() : CreatureScript("npc_cooshcoosh") { }
-
- struct npc_cooshcooshAI : public ScriptedAI
- {
- npc_cooshcooshAI(Creature* creature) : ScriptedAI(creature)
- {
- m_uiNormFaction = creature->GetFaction();
- Initialize();
- }
-
- void Initialize()
- {
- LightningBolt_Timer = 2000;
- }
-
- uint32 m_uiNormFaction;
- uint32 LightningBolt_Timer;
-
- void Reset() override
- {
- Initialize();
- if (me->GetFaction() != m_uiNormFaction)
- me->SetFaction(m_uiNormFaction);
- }
-
- void EnterCombat(Unit* /*who*/) override { }
-
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
-
- if (LightningBolt_Timer <= diff)
- {
- DoCastVictim(SPELL_LIGHTNING_BOLT);
- LightningBolt_Timer = 5000;
- } else LightningBolt_Timer -= diff;
-
- DoMeleeAttackIfReady();
- }
-
- bool GossipHello(Player* player) override
- {
- if (player->GetQuestStatus(QUEST_CRACK_SKULLS) == QUEST_STATUS_INCOMPLETE)
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_COOSH, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
-
- SendGossipMenuFor(player, 9441, me->GetGUID());
- return true;
- }
-
- bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
- {
- uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
- ClearGossipMenuFor(player);
- if (action == GOSSIP_ACTION_INFO_DEF)
- {
- CloseGossipMenuFor(player);
- me->SetFaction(FACTION_OGRE);
- AttackStart(player);
- }
- return true;
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_cooshcooshAI(creature);
- }
-};
-
-/*######
-## 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."
-
-class npc_elder_kuruti : public CreatureScript
-{
-public:
- npc_elder_kuruti() : CreatureScript("npc_elder_kuruti") { }
-
- struct npc_elder_kurutiAI : public ScriptedAI
- {
- npc_elder_kurutiAI(Creature* creature) : ScriptedAI(creature) { }
-
- bool GossipHello(Player* player) override
- {
- if (player->GetQuestStatus(9803) == QUEST_STATUS_INCOMPLETE)
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_KUR1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
-
- SendGossipMenuFor(player, 9226, me->GetGUID());
- return true;
- }
-
- bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
- {
- uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
- ClearGossipMenuFor(player);
- switch (action)
- {
- case GOSSIP_ACTION_INFO_DEF:
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_KUR2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- SendGossipMenuFor(player, 9227, me->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF + 1:
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_KUR3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
- SendGossipMenuFor(player, 9229, me->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF + 2:
- {
- if (!player->HasItemCount(24573))
- {
- ItemPosCountVec dest;
- uint32 itemId = 24573;
- InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemId, 1, nullptr);
- if (msg == EQUIP_ERR_OK)
- {
- player->StoreNewItem(dest, itemId, true);
- }
- else
- player->SendEquipError(msg, nullptr, nullptr, itemId);
- }
- SendGossipMenuFor(player, 9231, me->GetGUID());
- break;
- }
- }
- return true;
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_elder_kurutiAI(creature);
- }
-};
-
-/*######
## npc_kayra_longmane
######*/
@@ -330,13 +175,13 @@ class npc_kayra_longmane : public CreatureScript
public:
npc_kayra_longmane() : CreatureScript("npc_kayra_longmane") { }
- struct npc_kayra_longmaneAI : public npc_escortAI
+ struct npc_kayra_longmaneAI : public EscortAI
{
- npc_kayra_longmaneAI(Creature* creature) : npc_escortAI(creature) { }
+ npc_kayra_longmaneAI(Creature* creature) : EscortAI(creature) { }
void Reset() override { }
- void WaypointReached(uint32 waypointId) override
+ void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
Player* player = GetPlayerForEscort();
if (!player)
@@ -391,7 +236,5 @@ public:
void AddSC_zangarmarsh()
{
new npcs_ashyen_and_keleth();
- new npc_cooshcoosh();
- new npc_elder_kuruti();
new npc_kayra_longmane();
}
diff --git a/src/server/scripts/Pet/pet_hunter.cpp b/src/server/scripts/Pet/pet_hunter.cpp
index 20dcf5fb5d7..ed5f9ea48ed 100644
--- a/src/server/scripts/Pet/pet_hunter.cpp
+++ b/src/server/scripts/Pet/pet_hunter.cpp
@@ -236,7 +236,7 @@ class spell_pet_guard_dog : public SpellScriptLoader
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
- caster->CastSpell((Unit*)nullptr, SPELL_PET_GUARD_DOG_HAPPINESS, true, nullptr, aurEff);
+ caster->CastSpell(nullptr, SPELL_PET_GUARD_DOG_HAPPINESS, true, nullptr, aurEff);
float addThreat = CalculatePct(ASSERT_NOTNULL(eventInfo.GetSpellInfo())->Effects[EFFECT_0].CalcValue(caster), aurEff->GetAmount());
eventInfo.GetProcTarget()->GetThreatManager().AddThreat(caster, addThreat, GetSpellInfo(), false, true);
@@ -288,7 +288,7 @@ class spell_pet_silverback : public SpellScriptLoader
PreventDefaultAction();
uint32 spellId = triggerSpell[GetSpellInfo()->GetRank() - 1];
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, spellId, true, nullptr, aurEff);
+ eventInfo.GetActor()->CastSpell(nullptr, spellId, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp
index bd2e36bc30f..1cbe0537563 100644
--- a/src/server/scripts/Spells/spell_dk.cpp
+++ b/src/server/scripts/Spells/spell_dk.cpp
@@ -1546,7 +1546,7 @@ class spell_dk_pvp_4p_bonus : public SpellScriptLoader
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActionTarget()->CastSpell((Unit*)nullptr, SPELL_DK_RUNIC_RETURN, true, nullptr, aurEff);
+ eventInfo.GetActionTarget()->CastSpell(nullptr, SPELL_DK_RUNIC_RETURN, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp
index d57bd1e3008..0a4b7ae303e 100644
--- a/src/server/scripts/Spells/spell_druid.cpp
+++ b/src/server/scripts/Spells/spell_druid.cpp
@@ -495,7 +495,7 @@ class spell_dru_glyph_of_barkskin : public SpellScriptLoader
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_DRUID_BARKSKIN_01, true, nullptr, aurEff);
+ eventInfo.GetActor()->CastSpell(nullptr, SPELL_DRUID_BARKSKIN_01, true, nullptr, aurEff);
}
void Register() override
@@ -1160,7 +1160,7 @@ class spell_dru_omen_of_clarity : public SpellScriptLoader
{
Unit* target = GetTarget();
if (target->HasAura(SPELL_DRUID_BALANCE_T10_BONUS))
- target->CastSpell((Unit*)nullptr, SPELL_DRUID_BALANCE_T10_BONUS_PROC, true, nullptr, aurEff);
+ target->CastSpell(nullptr, SPELL_DRUID_BALANCE_T10_BONUS_PROC, true, nullptr, aurEff);
}
void Register() override
@@ -1874,7 +1874,7 @@ class spell_dru_t4_2p_bonus : public SpellScriptLoader
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_DRUID_INFUSION, true, nullptr, aurEff);
+ eventInfo.GetActor()->CastSpell(nullptr, SPELL_DRUID_INFUSION, true, nullptr, aurEff);
}
void Register() override
@@ -1940,7 +1940,7 @@ class spell_dru_item_t6_trinket : public SpellScriptLoader
return;
if (roll_chance_i(chance))
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, spellId, true, nullptr, aurEff);
+ eventInfo.GetActor()->CastSpell(nullptr, spellId, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index cbec8270e18..1b06b8c3a4a 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -42,39 +42,28 @@
#include "SpellScript.h"
#include "Vehicle.h"
-class spell_gen_absorb0_hitlimit1 : public SpellScriptLoader
+class spell_gen_absorb0_hitlimit1 : public AuraScript
{
- public:
- spell_gen_absorb0_hitlimit1() : SpellScriptLoader("spell_gen_absorb0_hitlimit1") { }
-
- class spell_gen_absorb0_hitlimit1_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_absorb0_hitlimit1_AuraScript);
-
- uint32 limit = 0;
+ PrepareAuraScript(spell_gen_absorb0_hitlimit1);
- bool Load() override
- {
- // Max absorb stored in 1 dummy effect
- limit = GetSpellInfo()->Effects[EFFECT_1].CalcValue();
- return true;
- }
+ uint32 limit = 0;
- void Absorb(AuraEffect* /*aurEff*/, DamageInfo& /*dmgInfo*/, uint32& absorbAmount)
- {
- absorbAmount = std::min(limit, absorbAmount);
- }
+ bool Load() override
+ {
+ // Max absorb stored in 1 dummy effect
+ limit = GetSpellInfo()->Effects[EFFECT_1].CalcValue();
+ return true;
+ }
- void Register() override
- {
- OnEffectAbsorb += AuraEffectAbsorbFn(spell_gen_absorb0_hitlimit1_AuraScript::Absorb, EFFECT_0);
- }
- };
+ void Absorb(AuraEffect* /*aurEff*/, DamageInfo& /*dmgInfo*/, uint32& absorbAmount)
+ {
+ absorbAmount = std::min(limit, absorbAmount);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_absorb0_hitlimit1_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectAbsorb += AuraEffectAbsorbFn(spell_gen_absorb0_hitlimit1::Absorb, EFFECT_0);
+ }
};
// 28764 - Adaptive Warding (Frostfire Regalia Set)
@@ -87,115 +76,93 @@ enum AdaptiveWarding
SPELL_GEN_ADAPTIVE_WARDING_ARCANE = 28770
};
-class spell_gen_adaptive_warding : public SpellScriptLoader
+class spell_gen_adaptive_warding : public AuraScript
{
- public:
- spell_gen_adaptive_warding() : SpellScriptLoader("spell_gen_adaptive_warding") { }
-
- class spell_gen_adaptive_warding_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_adaptive_warding_AuraScript);
+ PrepareAuraScript(spell_gen_adaptive_warding);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_GEN_ADAPTIVE_WARDING_FIRE,
- SPELL_GEN_ADAPTIVE_WARDING_NATURE,
- SPELL_GEN_ADAPTIVE_WARDING_FROST,
- SPELL_GEN_ADAPTIVE_WARDING_SHADOW,
- SPELL_GEN_ADAPTIVE_WARDING_ARCANE
- });
- }
-
- bool CheckProc(ProcEventInfo& eventInfo)
- {
- DamageInfo* damageInfo = eventInfo.GetDamageInfo();
- if (!damageInfo || !damageInfo->GetSpellInfo())
- return false;
-
- // find Mage Armor
- if (!GetTarget()->GetAuraEffect(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT, SPELLFAMILY_MAGE, 0x10000000, 0x0, 0x0))
- return false;
-
- switch (GetFirstSchoolInMask(eventInfo.GetSchoolMask()))
- {
- case SPELL_SCHOOL_NORMAL:
- case SPELL_SCHOOL_HOLY:
- return false;
- default:
- break;
- }
- return true;
- }
-
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
+ {
+ SPELL_GEN_ADAPTIVE_WARDING_FIRE,
+ SPELL_GEN_ADAPTIVE_WARDING_NATURE,
+ SPELL_GEN_ADAPTIVE_WARDING_FROST,
+ SPELL_GEN_ADAPTIVE_WARDING_SHADOW,
+ SPELL_GEN_ADAPTIVE_WARDING_ARCANE
+ });
+ }
- uint32 spellId = 0;
- switch (GetFirstSchoolInMask(eventInfo.GetSchoolMask()))
- {
- case SPELL_SCHOOL_FIRE:
- spellId = SPELL_GEN_ADAPTIVE_WARDING_FIRE;
- break;
- case SPELL_SCHOOL_NATURE:
- spellId = SPELL_GEN_ADAPTIVE_WARDING_NATURE;
- break;
- case SPELL_SCHOOL_FROST:
- spellId = SPELL_GEN_ADAPTIVE_WARDING_FROST;
- break;
- case SPELL_SCHOOL_SHADOW:
- spellId = SPELL_GEN_ADAPTIVE_WARDING_SHADOW;
- break;
- case SPELL_SCHOOL_ARCANE:
- spellId = SPELL_GEN_ADAPTIVE_WARDING_ARCANE;
- break;
- default:
- return;
- }
- GetTarget()->CastSpell(GetTarget(), spellId, true, nullptr, aurEff);
- }
+ bool CheckProc(ProcEventInfo& eventInfo)
+ {
+ DamageInfo* damageInfo = eventInfo.GetDamageInfo();
+ if (!damageInfo || !damageInfo->GetSpellInfo())
+ return false;
- void Register() override
- {
- DoCheckProc += AuraCheckProcFn(spell_gen_adaptive_warding_AuraScript::CheckProc);
- OnEffectProc += AuraEffectProcFn(spell_gen_adaptive_warding_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
- }
- };
+ // find Mage Armor
+ if (!GetTarget()->GetAuraEffect(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT, SPELLFAMILY_MAGE, 0x10000000, 0x0, 0x0))
+ return false;
- AuraScript* GetAuraScript() const override
+ switch (GetFirstSchoolInMask(eventInfo.GetSchoolMask()))
{
- return new spell_gen_adaptive_warding_AuraScript();
+ case SPELL_SCHOOL_NORMAL:
+ case SPELL_SCHOOL_HOLY:
+ return false;
+ default:
+ break;
}
-};
+ return true;
+ }
-class spell_gen_allow_cast_from_item_only : public SpellScriptLoader
-{
- public:
- spell_gen_allow_cast_from_item_only() : SpellScriptLoader("spell_gen_allow_cast_from_item_only") { }
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+
+ uint32 spellId = 0;
+ switch (GetFirstSchoolInMask(eventInfo.GetSchoolMask()))
+ {
+ case SPELL_SCHOOL_FIRE:
+ spellId = SPELL_GEN_ADAPTIVE_WARDING_FIRE;
+ break;
+ case SPELL_SCHOOL_NATURE:
+ spellId = SPELL_GEN_ADAPTIVE_WARDING_NATURE;
+ break;
+ case SPELL_SCHOOL_FROST:
+ spellId = SPELL_GEN_ADAPTIVE_WARDING_FROST;
+ break;
+ case SPELL_SCHOOL_SHADOW:
+ spellId = SPELL_GEN_ADAPTIVE_WARDING_SHADOW;
+ break;
+ case SPELL_SCHOOL_ARCANE:
+ spellId = SPELL_GEN_ADAPTIVE_WARDING_ARCANE;
+ break;
+ default:
+ return;
+ }
+ GetTarget()->CastSpell(GetTarget(), spellId, true, nullptr, aurEff);
+ }
- class spell_gen_allow_cast_from_item_only_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_allow_cast_from_item_only_SpellScript);
+ void Register() override
+ {
+ DoCheckProc += AuraCheckProcFn(spell_gen_adaptive_warding::CheckProc);
+ OnEffectProc += AuraEffectProcFn(spell_gen_adaptive_warding::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
+ }
+};
- SpellCastResult CheckRequirement()
- {
- if (!GetCastItem())
- return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW;
- return SPELL_CAST_OK;
- }
+class spell_gen_allow_cast_from_item_only : public SpellScript
+{
+ PrepareSpellScript(spell_gen_allow_cast_from_item_only);
- void Register() override
- {
- OnCheckCast += SpellCheckCastFn(spell_gen_allow_cast_from_item_only_SpellScript::CheckRequirement);
- }
- };
+ SpellCastResult CheckRequirement()
+ {
+ if (!GetCastItem())
+ return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW;
+ return SPELL_CAST_OK;
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_allow_cast_from_item_only_SpellScript();
- }
+ void Register() override
+ {
+ OnCheckCast += SpellCheckCastFn(spell_gen_allow_cast_from_item_only::CheckRequirement);
+ }
};
enum AnimalBloodPoolSpell
@@ -204,74 +171,52 @@ enum AnimalBloodPoolSpell
SPELL_SPAWN_BLOOD_POOL = 63471
};
-class spell_gen_animal_blood : public SpellScriptLoader
+class spell_gen_animal_blood : public AuraScript
{
- public:
- spell_gen_animal_blood() : SpellScriptLoader("spell_gen_animal_blood") { }
-
- class spell_gen_animal_blood_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_animal_blood_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_SPAWN_BLOOD_POOL });
- }
+ PrepareAuraScript(spell_gen_animal_blood);
- void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- // Remove all auras with spell id 46221, except the one currently being applied
- while (Aura* aur = GetUnitOwner()->GetOwnedAura(SPELL_ANIMAL_BLOOD, ObjectGuid::Empty, ObjectGuid::Empty, 0, GetAura()))
- GetUnitOwner()->RemoveOwnedAura(aur);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SPAWN_BLOOD_POOL });
+ }
- void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- if (Unit* owner = GetUnitOwner())
- if (owner->IsInWater())
- owner->CastSpell(owner, SPELL_SPAWN_BLOOD_POOL, true);
- }
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ // Remove all auras with spell id 46221, except the one currently being applied
+ while (Aura* aur = GetUnitOwner()->GetOwnedAura(SPELL_ANIMAL_BLOOD, ObjectGuid::Empty, ObjectGuid::Empty, 0, GetAura()))
+ GetUnitOwner()->RemoveOwnedAura(aur);
+ }
- void Register() override
- {
- AfterEffectApply += AuraEffectRemoveFn(spell_gen_animal_blood_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
- AfterEffectRemove += AuraEffectRemoveFn(spell_gen_animal_blood_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
- }
- };
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* owner = GetUnitOwner())
+ if (owner->IsInWater())
+ owner->CastSpell(owner, SPELL_SPAWN_BLOOD_POOL, true);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_animal_blood_AuraScript();
- }
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectRemoveFn(spell_gen_animal_blood::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_gen_animal_blood::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
+ }
};
// 41337 Aura of Anger
-class spell_gen_aura_of_anger : public SpellScriptLoader
+class spell_gen_aura_of_anger : public AuraScript
{
- public:
- spell_gen_aura_of_anger() : SpellScriptLoader("spell_gen_aura_of_anger") { }
-
- class spell_gen_aura_of_anger_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_aura_of_anger_AuraScript);
-
- void HandleEffectPeriodicUpdate(AuraEffect* aurEff)
- {
- if (AuraEffect* aurEff1 = aurEff->GetBase()->GetEffect(EFFECT_1))
- aurEff1->ChangeAmount(aurEff1->GetAmount() + 5);
- aurEff->SetAmount(100 * aurEff->GetTickNumber());
- }
+ PrepareAuraScript(spell_gen_aura_of_anger);
- void Register() override
- {
- OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_gen_aura_of_anger_AuraScript::HandleEffectPeriodicUpdate, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
- }
- };
+ void HandleEffectPeriodicUpdate(AuraEffect* aurEff)
+ {
+ if (AuraEffect* aurEff1 = aurEff->GetBase()->GetEffect(EFFECT_1))
+ aurEff1->ChangeAmount(aurEff1->GetAmount() + 5);
+ aurEff->SetAmount(100 * aurEff->GetTickNumber());
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_aura_of_anger_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_gen_aura_of_anger::HandleEffectPeriodicUpdate, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
+ }
};
enum ServiceUniform
@@ -284,94 +229,72 @@ enum ServiceUniform
MODEL_GOBLIN_FEMALE = 31003
};
-class spell_gen_aura_service_uniform : public SpellScriptLoader
+class spell_gen_aura_service_uniform : public AuraScript
{
- public:
- spell_gen_aura_service_uniform() : SpellScriptLoader("spell_gen_aura_service_uniform") { }
-
- class spell_gen_aura_service_uniform_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_aura_service_uniform_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_SERVICE_UNIFORM });
- }
-
- void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- // Apply model goblin
- Unit* target = GetTarget();
- if (target->GetTypeId() == TYPEID_PLAYER)
- {
- if (target->getGender() == GENDER_MALE)
- target->SetDisplayId(MODEL_GOBLIN_MALE);
- else
- target->SetDisplayId(MODEL_GOBLIN_FEMALE);
- }
- }
+ PrepareAuraScript(spell_gen_aura_service_uniform);
- void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- Unit* target = GetTarget();
- if (target->GetTypeId() == TYPEID_PLAYER)
- target->RestoreDisplayId();
- }
-
- void Register() override
- {
- AfterEffectApply += AuraEffectRemoveFn(spell_gen_aura_service_uniform_AuraScript::OnApply, EFFECT_0, SPELL_AURA_TRANSFORM, AURA_EFFECT_HANDLE_REAL);
- AfterEffectRemove += AuraEffectRemoveFn(spell_gen_aura_service_uniform_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_TRANSFORM, AURA_EFFECT_HANDLE_REAL);
- }
- };
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SERVICE_UNIFORM });
+ }
- AuraScript* GetAuraScript() const override
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ // Apply model goblin
+ Unit* target = GetTarget();
+ if (target->GetTypeId() == TYPEID_PLAYER)
{
- return new spell_gen_aura_service_uniform_AuraScript();
+ if (target->getGender() == GENDER_MALE)
+ target->SetDisplayId(MODEL_GOBLIN_MALE);
+ else
+ target->SetDisplayId(MODEL_GOBLIN_FEMALE);
}
-};
-
-class spell_gen_av_drekthar_presence : public SpellScriptLoader
-{
- public:
- spell_gen_av_drekthar_presence() : SpellScriptLoader("spell_gen_av_drekthar_presence") { }
+ }
- class spell_gen_av_drekthar_presence_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_av_drekthar_presence_AuraScript);
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* target = GetTarget();
+ if (target->GetTypeId() == TYPEID_PLAYER)
+ target->RestoreDisplayId();
+ }
- bool CheckAreaTarget(Unit* target)
- {
- switch (target->GetEntry())
- {
- // alliance
- case 14762: // Dun Baldar North Marshal
- case 14763: // Dun Baldar South Marshal
- case 14764: // Icewing Marshal
- case 14765: // Stonehearth Marshal
- case 11948: // Vandar Stormspike
- // horde
- case 14772: // East Frostwolf Warmaster
- case 14776: // Tower Point Warmaster
- case 14773: // Iceblood Warmaster
- case 14777: // West Frostwolf Warmaster
- case 11946: // Drek'thar
- return true;
- default:
- return false;
- }
- }
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectRemoveFn(spell_gen_aura_service_uniform::OnApply, EFFECT_0, SPELL_AURA_TRANSFORM, AURA_EFFECT_HANDLE_REAL);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_gen_aura_service_uniform::OnRemove, EFFECT_0, SPELL_AURA_TRANSFORM, AURA_EFFECT_HANDLE_REAL);
+ }
+};
- void Register() override
- {
- DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_gen_av_drekthar_presence_AuraScript::CheckAreaTarget);
- }
- };
+class spell_gen_av_drekthar_presence : public AuraScript
+{
+ PrepareAuraScript(spell_gen_av_drekthar_presence);
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_av_drekthar_presence_AuraScript();
+ bool CheckAreaTarget(Unit* target)
+ {
+ switch (target->GetEntry())
+ {
+ // alliance
+ case 14762: // Dun Baldar North Marshal
+ case 14763: // Dun Baldar South Marshal
+ case 14764: // Icewing Marshal
+ case 14765: // Stonehearth Marshal
+ case 11948: // Vandar Stormspike
+ // horde
+ case 14772: // East Frostwolf Warmaster
+ case 14776: // Tower Point Warmaster
+ case 14773: // Iceblood Warmaster
+ case 14777: // West Frostwolf Warmaster
+ case 11946: // Drek'thar
+ return true;
+ default:
+ return false;
}
+ }
+
+ void Register() override
+ {
+ DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_gen_av_drekthar_presence::CheckAreaTarget);
+ }
};
enum GenericBandage
@@ -379,47 +302,36 @@ enum GenericBandage
SPELL_RECENTLY_BANDAGED = 11196
};
-class spell_gen_bandage : public SpellScriptLoader
+class spell_gen_bandage : public SpellScript
{
- public:
- spell_gen_bandage() : SpellScriptLoader("spell_gen_bandage") { }
-
- class spell_gen_bandage_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_bandage_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_RECENTLY_BANDAGED });
- }
-
- SpellCastResult CheckCast()
- {
- if (Unit* target = GetExplTargetUnit())
- {
- if (target->HasAura(SPELL_RECENTLY_BANDAGED))
- return SPELL_FAILED_TARGET_AURASTATE;
- }
- return SPELL_CAST_OK;
- }
-
- void HandleScript()
- {
- if (Unit* target = GetHitUnit())
- GetCaster()->CastSpell(target, SPELL_RECENTLY_BANDAGED, true);
- }
+ PrepareSpellScript(spell_gen_bandage);
- void Register() override
- {
- OnCheckCast += SpellCheckCastFn(spell_gen_bandage_SpellScript::CheckCast);
- AfterHit += SpellHitFn(spell_gen_bandage_SpellScript::HandleScript);
- }
- };
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_RECENTLY_BANDAGED });
+ }
- SpellScript* GetSpellScript() const override
+ SpellCastResult CheckCast()
+ {
+ if (Unit* target = GetExplTargetUnit())
{
- return new spell_gen_bandage_SpellScript();
+ if (target->HasAura(SPELL_RECENTLY_BANDAGED))
+ return SPELL_FAILED_TARGET_AURASTATE;
}
+ return SPELL_CAST_OK;
+ }
+
+ void HandleScript()
+ {
+ if (Unit* target = GetHitUnit())
+ GetCaster()->CastSpell(target, SPELL_RECENTLY_BANDAGED, true);
+ }
+
+ void Register() override
+ {
+ OnCheckCast += SpellCheckCastFn(spell_gen_bandage::CheckCast);
+ AfterHit += SpellHitFn(spell_gen_bandage::HandleScript);
+ }
};
// Blood Reserve - 64568
@@ -429,50 +341,39 @@ enum BloodReserve
SPELL_GEN_BLOOD_RESERVE_HEAL = 64569
};
-class spell_gen_blood_reserve : public SpellScriptLoader
+class spell_gen_blood_reserve : public AuraScript
{
- public:
- spell_gen_blood_reserve() : SpellScriptLoader("spell_gen_blood_reserve") { }
-
- class spell_gen_blood_reserve_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_blood_reserve_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_GEN_BLOOD_RESERVE_HEAL });
- }
+ PrepareAuraScript(spell_gen_blood_reserve);
- bool CheckProc(ProcEventInfo& eventInfo)
- {
- if (DamageInfo* dmgInfo = eventInfo.GetDamageInfo())
- if (Unit* caster = eventInfo.GetActionTarget())
- if (caster->HealthBelowPctDamaged(35, dmgInfo->GetDamage()))
- return true;
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_GEN_BLOOD_RESERVE_HEAL });
+ }
- return false;
- }
+ bool CheckProc(ProcEventInfo& eventInfo)
+ {
+ if (DamageInfo* dmgInfo = eventInfo.GetDamageInfo())
+ if (Unit* caster = eventInfo.GetActionTarget())
+ if (caster->HealthBelowPctDamaged(35, dmgInfo->GetDamage()))
+ return true;
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
+ return false;
+ }
- Unit* caster = eventInfo.GetActionTarget();
- caster->CastCustomSpell(SPELL_GEN_BLOOD_RESERVE_HEAL, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), caster, TRIGGERED_FULL_MASK, nullptr, aurEff);
- caster->RemoveAura(SPELL_GEN_BLOOD_RESERVE_AURA);
- }
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
- void Register() override
- {
- DoCheckProc += AuraCheckProcFn(spell_gen_blood_reserve_AuraScript::CheckProc);
- OnEffectProc += AuraEffectProcFn(spell_gen_blood_reserve_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
- }
- };
+ Unit* caster = eventInfo.GetActionTarget();
+ caster->CastCustomSpell(SPELL_GEN_BLOOD_RESERVE_HEAL, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), caster, TRIGGERED_FULL_MASK, nullptr, aurEff);
+ caster->RemoveAura(SPELL_GEN_BLOOD_RESERVE_AURA);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_blood_reserve_AuraScript();
- }
+ void Register() override
+ {
+ DoCheckProc += AuraCheckProcFn(spell_gen_blood_reserve::CheckProc);
+ OnEffectProc += AuraEffectProcFn(spell_gen_blood_reserve::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
+ }
};
// Blade Warding - 64440
@@ -481,46 +382,35 @@ enum BladeWarding
SPELL_GEN_BLADE_WARDING_TRIGGERED = 64442
};
-class spell_gen_blade_warding : public SpellScriptLoader
+class spell_gen_blade_warding : public AuraScript
{
- public:
- spell_gen_blade_warding() : SpellScriptLoader("spell_gen_blade_warding") { }
+ PrepareAuraScript(spell_gen_blade_warding);
- class spell_gen_blade_warding_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_blade_warding_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_GEN_BLADE_WARDING_TRIGGERED });
- }
-
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_GEN_BLADE_WARDING_TRIGGERED });
+ }
- Unit* caster = eventInfo.GetActionTarget();
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_GEN_BLADE_WARDING_TRIGGERED);
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
- uint8 stacks = GetStackAmount();
- int32 bp = 0;
+ Unit* caster = eventInfo.GetActionTarget();
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_GEN_BLADE_WARDING_TRIGGERED);
- for (uint8 i = 0; i < stacks; ++i)
- bp += spellInfo->Effects[EFFECT_0].CalcValue(caster);
+ uint8 stacks = GetStackAmount();
+ int32 bp = 0;
- caster->CastCustomSpell(SPELL_GEN_BLADE_WARDING_TRIGGERED, SPELLVALUE_BASE_POINT0, bp, eventInfo.GetActor(), TRIGGERED_FULL_MASK, nullptr, aurEff);
- }
+ for (uint8 i = 0; i < stacks; ++i)
+ bp += spellInfo->Effects[EFFECT_0].CalcValue(caster);
- void Register() override
- {
- OnEffectProc += AuraEffectProcFn(spell_gen_blade_warding_AuraScript::HandleProc, EFFECT_1, SPELL_AURA_PROC_TRIGGER_SPELL);
- }
- };
+ caster->CastCustomSpell(SPELL_GEN_BLADE_WARDING_TRIGGERED, SPELLVALUE_BASE_POINT0, bp, eventInfo.GetActor(), TRIGGERED_FULL_MASK, nullptr, aurEff);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_blade_warding_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_gen_blade_warding::HandleProc, EFFECT_1, SPELL_AURA_PROC_TRIGGER_SPELL);
+ }
};
enum Bonked
@@ -530,42 +420,31 @@ enum Bonked
SPELL_ON_GUARD = 62972
};
-class spell_gen_bonked : public SpellScriptLoader
+class spell_gen_bonked : public SpellScript
{
- public:
- spell_gen_bonked() : SpellScriptLoader("spell_gen_bonked") { }
+ PrepareSpellScript(spell_gen_bonked);
- class spell_gen_bonked_SpellScript : public SpellScript
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Player* target = GetHitPlayer())
{
- PrepareSpellScript(spell_gen_bonked_SpellScript);
-
- void HandleScript(SpellEffIndex /*effIndex*/)
- {
- if (Player* target = GetHitPlayer())
- {
- Aura const* aura = GetHitAura();
- if (!(aura && aura->GetStackAmount() == 3))
- return;
-
- target->CastSpell(target, SPELL_FOAM_SWORD_DEFEAT, true);
- target->RemoveAurasDueToSpell(SPELL_BONKED);
-
- if (Aura const* auraOnGuard = target->GetAura(SPELL_ON_GUARD))
- if (Item* item = target->GetItemByGuid(auraOnGuard->GetCastItemGUID()))
- target->DestroyItemCount(item->GetEntry(), 1, true);
- }
- }
+ Aura const* aura = GetHitAura();
+ if (!(aura && aura->GetStackAmount() == 3))
+ return;
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_bonked_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ target->CastSpell(target, SPELL_FOAM_SWORD_DEFEAT, true);
+ target->RemoveAurasDueToSpell(SPELL_BONKED);
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_bonked_SpellScript();
+ if (Aura const* auraOnGuard = target->GetAura(SPELL_ON_GUARD))
+ if (Item* item = target->GetItemByGuid(auraOnGuard->GetCastItemGUID()))
+ target->DestroyItemCount(item->GetEntry(), 1, true);
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_bonked::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
/* DOCUMENTATION: Break-Shield spells
@@ -678,70 +557,48 @@ class spell_gen_break_shield: public SpellScriptLoader
};
// 46394 Brutallus Burn
-class spell_gen_burn_brutallus : public SpellScriptLoader
+class spell_gen_burn_brutallus : public AuraScript
{
- public:
- spell_gen_burn_brutallus() : SpellScriptLoader("spell_gen_burn_brutallus") { }
-
- class spell_gen_burn_brutallus_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_burn_brutallus_AuraScript);
-
- void HandleEffectPeriodicUpdate(AuraEffect* aurEff)
- {
- if (aurEff->GetTickNumber() % 11 == 0)
- aurEff->SetAmount(aurEff->GetAmount() * 2);
- }
+ PrepareAuraScript(spell_gen_burn_brutallus);
- void Register() override
- {
- OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_gen_burn_brutallus_AuraScript::HandleEffectPeriodicUpdate, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
- }
- };
+ void HandleEffectPeriodicUpdate(AuraEffect* aurEff)
+ {
+ if (aurEff->GetTickNumber() % 11 == 0)
+ aurEff->SetAmount(aurEff->GetAmount() * 2);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_burn_brutallus_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_gen_burn_brutallus::HandleEffectPeriodicUpdate, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
+ }
};
// 48750 - Burning Depths Necrolyte Image
-class spell_gen_burning_depths_necrolyte_image : public SpellScriptLoader
+class spell_gen_burning_depths_necrolyte_image : public AuraScript
{
- public:
- spell_gen_burning_depths_necrolyte_image() : SpellScriptLoader("spell_gen_burning_depths_necrolyte_image") { }
-
- class spell_gen_burning_depths_necrolyte_image_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_burning_depths_necrolyte_image_AuraScript);
-
- bool Validate(SpellInfo const* spellInfo) override
- {
- return ValidateSpellInfo({ static_cast<uint32>(spellInfo->Effects[EFFECT_2].CalcValue()) });
- }
+ PrepareAuraScript(spell_gen_burning_depths_necrolyte_image);
- void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- if (Unit* caster = GetCaster())
- caster->CastSpell(GetTarget(), uint32(GetSpellInfo()->Effects[EFFECT_2].CalcValue()));
- }
+ bool Validate(SpellInfo const* spellInfo) override
+ {
+ return ValidateSpellInfo({ static_cast<uint32>(spellInfo->Effects[EFFECT_2].CalcValue()) });
+ }
- void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- GetTarget()->RemoveAurasDueToSpell(uint32(GetSpellInfo()->Effects[EFFECT_2].CalcValue()), GetCasterGUID());
- }
+ void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* caster = GetCaster())
+ caster->CastSpell(GetTarget(), uint32(GetSpellInfo()->Effects[EFFECT_2].CalcValue()));
+ }
- void Register() override
- {
- AfterEffectApply += AuraEffectApplyFn(spell_gen_burning_depths_necrolyte_image_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_TRANSFORM, AURA_EFFECT_HANDLE_REAL);
- AfterEffectRemove += AuraEffectRemoveFn(spell_gen_burning_depths_necrolyte_image_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_TRANSFORM, AURA_EFFECT_HANDLE_REAL);
- }
- };
+ void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->RemoveAurasDueToSpell(uint32(GetSpellInfo()->Effects[EFFECT_2].CalcValue()), GetCasterGUID());
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_burning_depths_necrolyte_image_AuraScript();
- }
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_gen_burning_depths_necrolyte_image::HandleApply, EFFECT_0, SPELL_AURA_TRANSFORM, AURA_EFFECT_HANDLE_REAL);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_gen_burning_depths_necrolyte_image::HandleRemove, EFFECT_0, SPELL_AURA_TRANSFORM, AURA_EFFECT_HANDLE_REAL);
+ }
};
enum CannibalizeSpells
@@ -749,52 +606,41 @@ enum CannibalizeSpells
SPELL_CANNIBALIZE_TRIGGERED = 20578
};
-class spell_gen_cannibalize : public SpellScriptLoader
+class spell_gen_cannibalize : public SpellScript
{
- public:
- spell_gen_cannibalize() : SpellScriptLoader("spell_gen_cannibalize") { }
+ PrepareSpellScript(spell_gen_cannibalize);
- class spell_gen_cannibalize_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_cannibalize_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_CANNIBALIZE_TRIGGERED });
- }
-
- SpellCastResult CheckIfCorpseNear()
- {
- Unit* caster = GetCaster();
- float max_range = GetSpellInfo()->GetMaxRange(false);
- WorldObject* result = nullptr;
- // search for nearby enemy corpse in range
- Trinity::AnyDeadUnitSpellTargetInRangeCheck check(caster, max_range, GetSpellInfo(), TARGET_CHECK_ENEMY);
- Trinity::WorldObjectSearcher<Trinity::AnyDeadUnitSpellTargetInRangeCheck> searcher(caster, result, check);
- Cell::VisitWorldObjects(caster, searcher, max_range);
- if (!result)
- Cell::VisitGridObjects(caster, searcher, max_range);
- if (!result)
- return SPELL_FAILED_NO_EDIBLE_CORPSES;
- return SPELL_CAST_OK;
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_CANNIBALIZE_TRIGGERED });
+ }
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- GetCaster()->CastSpell(GetCaster(), SPELL_CANNIBALIZE_TRIGGERED, false);
- }
+ SpellCastResult CheckIfCorpseNear()
+ {
+ Unit* caster = GetCaster();
+ float max_range = GetSpellInfo()->GetMaxRange(false);
+ WorldObject* result = nullptr;
+ // search for nearby enemy corpse in range
+ Trinity::AnyDeadUnitSpellTargetInRangeCheck check(caster, max_range, GetSpellInfo(), TARGET_CHECK_ENEMY);
+ Trinity::WorldObjectSearcher<Trinity::AnyDeadUnitSpellTargetInRangeCheck> searcher(caster, result, check);
+ Cell::VisitWorldObjects(caster, searcher, max_range);
+ if (!result)
+ Cell::VisitGridObjects(caster, searcher, max_range);
+ if (!result)
+ return SPELL_FAILED_NO_EDIBLE_CORPSES;
+ return SPELL_CAST_OK;
+ }
- void Register() override
- {
- OnEffectHit += SpellEffectFn(spell_gen_cannibalize_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- OnCheckCast += SpellCheckCastFn(spell_gen_cannibalize_SpellScript::CheckIfCorpseNear);
- }
- };
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->CastSpell(GetCaster(), SPELL_CANNIBALIZE_TRIGGERED, false);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_cannibalize_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHit += SpellEffectFn(spell_gen_cannibalize::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ OnCheckCast += SpellCheckCastFn(spell_gen_cannibalize::CheckIfCorpseNear);
+ }
};
enum ChaosBlast
@@ -802,65 +648,43 @@ enum ChaosBlast
SPELL_CHAOS_BLAST = 37675
};
-class spell_gen_chaos_blast : public SpellScriptLoader
+class spell_gen_chaos_blast : public SpellScript
{
- public:
- spell_gen_chaos_blast() : SpellScriptLoader("spell_gen_chaos_blast") { }
-
- class spell_gen_chaos_blast_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_chaos_blast_SpellScript);
+ PrepareSpellScript(spell_gen_chaos_blast);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_CHAOS_BLAST });
- }
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- int32 basepoints0 = 100;
- Unit* caster = GetCaster();
- if (Unit* target = GetHitUnit())
- caster->CastCustomSpell(target, SPELL_CHAOS_BLAST, &basepoints0, nullptr, nullptr, true);
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_chaos_blast_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_CHAOS_BLAST });
+ }
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ int32 basepoints0 = 100;
+ Unit* caster = GetCaster();
+ if (Unit* target = GetHitUnit())
+ caster->CastCustomSpell(target, SPELL_CHAOS_BLAST, &basepoints0, nullptr, nullptr, true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_chaos_blast_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_chaos_blast::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
-class spell_gen_clone : public SpellScriptLoader
+class spell_gen_clone : public SpellScript
{
- public:
- spell_gen_clone() : SpellScriptLoader("spell_gen_clone") { }
-
- class spell_gen_clone_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_clone_SpellScript);
+ PrepareSpellScript(spell_gen_clone);
- void HandleScriptEffect(SpellEffIndex effIndex)
- {
- PreventHitDefaultEffect(effIndex);
- GetHitUnit()->CastSpell(GetCaster(), uint32(GetEffectValue()), true);
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_clone_SpellScript::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
- OnEffectHitTarget += SpellEffectFn(spell_gen_clone_SpellScript::HandleScriptEffect, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ void HandleScriptEffect(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ GetHitUnit()->CastSpell(GetCaster(), uint32(GetEffectValue()), true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_clone_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_clone::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
+ OnEffectHitTarget += SpellEffectFn(spell_gen_clone::HandleScriptEffect, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
enum CloneWeaponSpells
@@ -875,147 +699,125 @@ enum CloneWeaponSpells
SPELL_COPY_RANGED_AURA = 57594
};
-class spell_gen_clone_weapon : public SpellScriptLoader
+class spell_gen_clone_weapon : public SpellScript
{
- public:
- spell_gen_clone_weapon() : SpellScriptLoader("spell_gen_clone_weapon") { }
-
- class spell_gen_clone_weapon_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_clone_weapon_SpellScript);
-
- void HandleScriptEffect(SpellEffIndex effIndex)
- {
- PreventHitDefaultEffect(effIndex);
- GetHitUnit()->CastSpell(GetCaster(), uint32(GetEffectValue()), true);
- }
+ PrepareSpellScript(spell_gen_clone_weapon);
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_clone_weapon_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ void HandleScriptEffect(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ GetHitUnit()->CastSpell(GetCaster(), uint32(GetEffectValue()), true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_clone_weapon_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_clone_weapon::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
-class spell_gen_clone_weapon_aura : public SpellScriptLoader
+class spell_gen_clone_weapon_aura : public AuraScript
{
- public:
- spell_gen_clone_weapon_aura() : SpellScriptLoader("spell_gen_clone_weapon_aura") { }
+ PrepareAuraScript(spell_gen_clone_weapon_aura);
- class spell_gen_clone_weapon_auraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_clone_weapon_auraScript);
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
+ {
+ SPELL_COPY_WEAPON_AURA,
+ SPELL_COPY_WEAPON_2_AURA,
+ SPELL_COPY_WEAPON_3_AURA,
+ SPELL_COPY_OFFHAND_AURA,
+ SPELL_COPY_OFFHAND_2_AURA,
+ SPELL_COPY_RANGED_AURA
+ });
+ }
- bool Validate(SpellInfo const* /*spellInfo*/) override
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* caster = GetCaster();
+ Unit* target = GetTarget();
+ if (!caster)
+ return;
+
+ switch (GetSpellInfo()->Id)
+ {
+ case SPELL_COPY_WEAPON_AURA:
+ case SPELL_COPY_WEAPON_2_AURA:
+ case SPELL_COPY_WEAPON_3_AURA:
{
- return ValidateSpellInfo(
+ prevItem = target->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID);
+
+ if (Player* player = caster->ToPlayer())
{
- SPELL_COPY_WEAPON_AURA,
- SPELL_COPY_WEAPON_2_AURA,
- SPELL_COPY_WEAPON_3_AURA,
- SPELL_COPY_OFFHAND_AURA,
- SPELL_COPY_OFFHAND_2_AURA,
- SPELL_COPY_RANGED_AURA
- });
+ if (Item* mainItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND))
+ target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, mainItem->GetEntry());
+ }
+ else
+ target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, caster->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID));
+ break;
}
-
- void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ case SPELL_COPY_OFFHAND_AURA:
+ case SPELL_COPY_OFFHAND_2_AURA:
{
- Unit* caster = GetCaster();
- Unit* target = GetTarget();
- if (!caster)
- return;
+ prevItem = target->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID) + 1;
- switch (GetSpellInfo()->Id)
+ if (Player* player = caster->ToPlayer())
{
- case SPELL_COPY_WEAPON_AURA:
- case SPELL_COPY_WEAPON_2_AURA:
- case SPELL_COPY_WEAPON_3_AURA:
- {
- prevItem = target->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID);
-
- if (Player* player = caster->ToPlayer())
- {
- if (Item* mainItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND))
- target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, mainItem->GetEntry());
- }
- else
- target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, caster->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID));
- break;
- }
- case SPELL_COPY_OFFHAND_AURA:
- case SPELL_COPY_OFFHAND_2_AURA:
- {
- prevItem = target->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID) + 1;
-
- if (Player* player = caster->ToPlayer())
- {
- if (Item* offItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND))
- target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, offItem->GetEntry());
- }
- else
- target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, caster->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1));
- break;
- }
- case SPELL_COPY_RANGED_AURA:
- {
- prevItem = target->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID) + 2;
-
- if (Player* player = caster->ToPlayer())
- {
- if (Item* rangedItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED))
- target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, rangedItem->GetEntry());
- }
- else
- target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, caster->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2));
- break;
- }
- default:
- break;
+ if (Item* offItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND))
+ target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, offItem->GetEntry());
}
+ else
+ target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, caster->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1));
+ break;
}
-
- void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ case SPELL_COPY_RANGED_AURA:
{
- Unit* target = GetTarget();
+ prevItem = target->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID) + 2;
- switch (GetSpellInfo()->Id)
+ if (Player* player = caster->ToPlayer())
{
- case SPELL_COPY_WEAPON_AURA:
- case SPELL_COPY_WEAPON_2_AURA:
- case SPELL_COPY_WEAPON_3_AURA:
- target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, prevItem);
- break;
- case SPELL_COPY_OFFHAND_AURA:
- case SPELL_COPY_OFFHAND_2_AURA:
- target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, prevItem);
- break;
- case SPELL_COPY_RANGED_AURA:
- target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, prevItem);
- break;
- default:
- break;
+ if (Item* rangedItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED))
+ target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, rangedItem->GetEntry());
}
+ else
+ target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, caster->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2));
+ break;
}
+ default:
+ break;
+ }
+ }
- void Register() override
- {
- OnEffectApply += AuraEffectApplyFn(spell_gen_clone_weapon_auraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
- OnEffectRemove += AuraEffectRemoveFn(spell_gen_clone_weapon_auraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
- }
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* target = GetTarget();
+
+ switch (GetSpellInfo()->Id)
+ {
+ case SPELL_COPY_WEAPON_AURA:
+ case SPELL_COPY_WEAPON_2_AURA:
+ case SPELL_COPY_WEAPON_3_AURA:
+ target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, prevItem);
+ break;
+ case SPELL_COPY_OFFHAND_AURA:
+ case SPELL_COPY_OFFHAND_2_AURA:
+ target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, prevItem);
+ break;
+ case SPELL_COPY_RANGED_AURA:
+ target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, prevItem);
+ break;
+ default:
+ break;
+ }
+ }
- uint32 prevItem = 0;
- };
+ void Register() override
+ {
+ OnEffectApply += AuraEffectApplyFn(spell_gen_clone_weapon_aura::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
+ OnEffectRemove += AuraEffectRemoveFn(spell_gen_clone_weapon_aura::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_clone_weapon_auraScript();
- }
+ uint32 prevItem = 0;
};
class spell_gen_count_pct_from_max_hp : public SpellScriptLoader
@@ -1063,86 +865,64 @@ enum CreateLanceSpells
SPELL_CREATE_LANCE_HORDE = 63919
};
-class spell_gen_create_lance : public SpellScriptLoader
+class spell_gen_create_lance : public SpellScript
{
- public:
- spell_gen_create_lance() : SpellScriptLoader("spell_gen_create_lance") { }
+ PrepareSpellScript(spell_gen_create_lance);
- class spell_gen_create_lance_SpellScript : public SpellScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareSpellScript(spell_gen_create_lance_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_CREATE_LANCE_ALLIANCE,
- SPELL_CREATE_LANCE_HORDE
- });
- }
-
- void HandleScript(SpellEffIndex effIndex)
- {
- PreventHitDefaultEffect(effIndex);
-
- if (Player* target = GetHitPlayer())
- {
- if (target->GetTeam() == ALLIANCE)
- GetCaster()->CastSpell(target, SPELL_CREATE_LANCE_ALLIANCE, true);
- else
- GetCaster()->CastSpell(target, SPELL_CREATE_LANCE_HORDE, true);
- }
- }
+ SPELL_CREATE_LANCE_ALLIANCE,
+ SPELL_CREATE_LANCE_HORDE
+ });
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_create_lance_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ void HandleScript(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
- SpellScript* GetSpellScript() const override
+ if (Player* target = GetHitPlayer())
{
- return new spell_gen_create_lance_SpellScript();
+ if (target->GetTeam() == ALLIANCE)
+ GetCaster()->CastSpell(target, SPELL_CREATE_LANCE_ALLIANCE, true);
+ else
+ GetCaster()->CastSpell(target, SPELL_CREATE_LANCE_HORDE, true);
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_create_lance::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
-class spell_gen_creature_permanent_feign_death : public SpellScriptLoader
+class spell_gen_creature_permanent_feign_death : public AuraScript
{
- public:
- spell_gen_creature_permanent_feign_death() : SpellScriptLoader("spell_gen_creature_permanent_feign_death") { }
-
- class spell_gen_creature_permanent_feign_death_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_creature_permanent_feign_death_AuraScript);
-
- void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- Unit* target = GetTarget();
- target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
- target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
+ PrepareAuraScript(spell_gen_creature_permanent_feign_death);
- if (target->GetTypeId() == TYPEID_UNIT)
- target->ToCreature()->SetReactState(REACT_PASSIVE);
- }
+ void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* target = GetTarget();
+ target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
+ target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
- void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- Unit* target = GetTarget();
- target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
- target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
- }
+ if (target->GetTypeId() == TYPEID_UNIT)
+ target->ToCreature()->SetReactState(REACT_PASSIVE);
+ }
- void Register() override
- {
- OnEffectApply += AuraEffectApplyFn(spell_gen_creature_permanent_feign_death_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
- OnEffectRemove += AuraEffectRemoveFn(spell_gen_creature_permanent_feign_death_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
- }
- };
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* target = GetTarget();
+ target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
+ target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_creature_permanent_feign_death_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectApply += AuraEffectApplyFn(spell_gen_creature_permanent_feign_death::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ OnEffectRemove += AuraEffectRemoveFn(spell_gen_creature_permanent_feign_death::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
};
enum DalaranDisguiseSpells
@@ -1233,50 +1013,38 @@ enum DamageReductionAura
SPELL_DAMAGE_REDUCTION_AURA = 68066
};
-class spell_gen_damage_reduction_aura : public SpellScriptLoader
+class spell_gen_damage_reduction_aura : public AuraScript
{
- public:
- spell_gen_damage_reduction_aura() : SpellScriptLoader("spell_gen_damage_reduction_aura") { }
-
- class spell_gen_damage_reduction_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_damage_reduction_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_DAMAGE_REDUCTION_AURA });
- }
-
- void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- Unit* target = GetTarget();
- target->CastSpell(target, SPELL_DAMAGE_REDUCTION_AURA, true);
- }
-
- void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- Unit* target = GetTarget();
- if (target->HasAura(SPELL_DAMAGE_REDUCTION_AURA) && !(target->HasAura(SPELL_BLESSING_OF_SANCTUARY) ||
- target->HasAura(SPELL_GREATER_BLESSING_OF_SANCTUARY) ||
- target->HasAura(SPELL_RENEWED_HOPE) ||
- target->HasAura(SPELL_VIGILANCE)))
- {
- target->RemoveAurasDueToSpell(SPELL_DAMAGE_REDUCTION_AURA);
- }
- }
+ PrepareAuraScript(spell_gen_damage_reduction_aura);
- void Register() override
- {
- OnEffectApply += AuraEffectApplyFn(spell_gen_damage_reduction_AuraScript::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
- OnEffectRemove += AuraEffectRemoveFn(spell_gen_damage_reduction_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_DAMAGE_REDUCTION_AURA });
+ }
- };
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* target = GetTarget();
+ target->CastSpell(target, SPELL_DAMAGE_REDUCTION_AURA, true);
+ }
- AuraScript* GetAuraScript() const override
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* target = GetTarget();
+ if (target->HasAura(SPELL_DAMAGE_REDUCTION_AURA) && !(target->HasAura(SPELL_BLESSING_OF_SANCTUARY) ||
+ target->HasAura(SPELL_GREATER_BLESSING_OF_SANCTUARY) ||
+ target->HasAura(SPELL_RENEWED_HOPE) ||
+ target->HasAura(SPELL_VIGILANCE)))
{
- return new spell_gen_damage_reduction_AuraScript();
+ target->RemoveAurasDueToSpell(SPELL_DAMAGE_REDUCTION_AURA);
}
+ }
+
+ void Register() override
+ {
+ OnEffectApply += AuraEffectApplyFn(spell_gen_damage_reduction_aura::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
+ OnEffectRemove += AuraEffectRemoveFn(spell_gen_damage_reduction_aura::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
+ }
};
enum DefendVisuals
@@ -1286,114 +1054,92 @@ enum DefendVisuals
SPELL_VISUAL_SHIELD_3 = 63132
};
-class spell_gen_defend : public SpellScriptLoader
+class spell_gen_defend : public AuraScript
{
- public:
- spell_gen_defend() : SpellScriptLoader("spell_gen_defend") { }
+ PrepareAuraScript(spell_gen_defend);
- class spell_gen_defend_AuraScript : public AuraScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareAuraScript(spell_gen_defend_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_VISUAL_SHIELD_1,
- SPELL_VISUAL_SHIELD_2,
- SPELL_VISUAL_SHIELD_3
- });
- }
-
- void RefreshVisualShields(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
- {
- if (GetCaster())
- {
- Unit* target = GetTarget();
+ SPELL_VISUAL_SHIELD_1,
+ SPELL_VISUAL_SHIELD_2,
+ SPELL_VISUAL_SHIELD_3
+ });
+ }
- for (uint8 i = 0; i < GetSpellInfo()->StackAmount; ++i)
- target->RemoveAurasDueToSpell(SPELL_VISUAL_SHIELD_1 + i);
+ void RefreshVisualShields(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetCaster())
+ {
+ Unit* target = GetTarget();
- target->CastSpell(target, SPELL_VISUAL_SHIELD_1 + GetAura()->GetStackAmount() - 1, true, nullptr, aurEff);
- }
- else
- GetTarget()->RemoveAurasDueToSpell(GetId());
- }
+ for (uint8 i = 0; i < GetSpellInfo()->StackAmount; ++i)
+ target->RemoveAurasDueToSpell(SPELL_VISUAL_SHIELD_1 + i);
- void RemoveVisualShields(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- for (uint8 i = 0; i < GetSpellInfo()->StackAmount; ++i)
- GetTarget()->RemoveAurasDueToSpell(SPELL_VISUAL_SHIELD_1 + i);
- }
+ target->CastSpell(target, SPELL_VISUAL_SHIELD_1 + GetAura()->GetStackAmount() - 1, true, nullptr, aurEff);
+ }
+ else
+ GetTarget()->RemoveAurasDueToSpell(GetId());
+ }
- void RemoveDummyFromDriver(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- if (Unit* caster = GetCaster())
- if (TempSummon* vehicle = caster->ToTempSummon())
- if (Unit* rider = vehicle->GetSummoner())
- rider->RemoveAurasDueToSpell(GetId());
- }
+ void RemoveVisualShields(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ for (uint8 i = 0; i < GetSpellInfo()->StackAmount; ++i)
+ GetTarget()->RemoveAurasDueToSpell(SPELL_VISUAL_SHIELD_1 + i);
+ }
- void Register() override
- {
- SpellInfo const* spell = sSpellMgr->AssertSpellInfo(m_scriptSpellId);
+ void RemoveDummyFromDriver(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* caster = GetCaster())
+ if (TempSummon* vehicle = caster->ToTempSummon())
+ if (Unit* rider = vehicle->GetSummoner())
+ rider->RemoveAurasDueToSpell(GetId());
+ }
- // Defend spells cast by NPCs (add visuals)
- if (spell->Effects[EFFECT_0].ApplyAuraName == SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN)
- {
- AfterEffectApply += AuraEffectApplyFn(spell_gen_defend_AuraScript::RefreshVisualShields, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
- OnEffectRemove += AuraEffectRemoveFn(spell_gen_defend_AuraScript::RemoveVisualShields, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK);
- }
+ void Register() override
+ {
+ SpellInfo const* spell = sSpellMgr->AssertSpellInfo(m_scriptSpellId);
- // Remove Defend spell from player when he dismounts
- if (spell->Effects[EFFECT_2].ApplyAuraName == SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN)
- OnEffectRemove += AuraEffectRemoveFn(spell_gen_defend_AuraScript::RemoveDummyFromDriver, EFFECT_2, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL);
+ // Defend spells cast by NPCs (add visuals)
+ if (spell->Effects[EFFECT_0].ApplyAuraName == SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN)
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_gen_defend::RefreshVisualShields, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
+ OnEffectRemove += AuraEffectRemoveFn(spell_gen_defend::RemoveVisualShields, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK);
+ }
- // Defend spells cast by players (add/remove visuals)
- if (spell->Effects[EFFECT_1].ApplyAuraName == SPELL_AURA_DUMMY)
- {
- AfterEffectApply += AuraEffectApplyFn(spell_gen_defend_AuraScript::RefreshVisualShields, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
- OnEffectRemove += AuraEffectRemoveFn(spell_gen_defend_AuraScript::RemoveVisualShields, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK);
- }
- }
- };
+ // Remove Defend spell from player when he dismounts
+ if (spell->Effects[EFFECT_2].ApplyAuraName == SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN)
+ OnEffectRemove += AuraEffectRemoveFn(spell_gen_defend::RemoveDummyFromDriver, EFFECT_2, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL);
- AuraScript* GetAuraScript() const override
+ // Defend spells cast by players (add/remove visuals)
+ if (spell->Effects[EFFECT_1].ApplyAuraName == SPELL_AURA_DUMMY)
{
- return new spell_gen_defend_AuraScript();
+ AfterEffectApply += AuraEffectApplyFn(spell_gen_defend::RefreshVisualShields, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
+ OnEffectRemove += AuraEffectRemoveFn(spell_gen_defend::RemoveVisualShields, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK);
}
+ }
};
-class spell_gen_despawn_self : public SpellScriptLoader
+class spell_gen_despawn_self : public SpellScript
{
- public:
- spell_gen_despawn_self() : SpellScriptLoader("spell_gen_despawn_self") { }
-
- class spell_gen_despawn_self_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_despawn_self_SpellScript);
-
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_UNIT;
- }
+ PrepareSpellScript(spell_gen_despawn_self);
- void HandleDummy(SpellEffIndex effIndex)
- {
- if (GetSpellInfo()->Effects[effIndex].Effect == SPELL_EFFECT_DUMMY || GetSpellInfo()->Effects[effIndex].Effect == SPELL_EFFECT_SCRIPT_EFFECT)
- GetCaster()->ToCreature()->DespawnOrUnsummon();
- }
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_UNIT;
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_despawn_self_SpellScript::HandleDummy, EFFECT_ALL, SPELL_EFFECT_ANY);
- }
- };
+ void HandleDummy(SpellEffIndex effIndex)
+ {
+ if (GetSpellInfo()->Effects[effIndex].Effect == SPELL_EFFECT_DUMMY || GetSpellInfo()->Effects[effIndex].Effect == SPELL_EFFECT_SCRIPT_EFFECT)
+ GetCaster()->ToCreature()->DespawnOrUnsummon();
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_despawn_self_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_despawn_self::HandleDummy, EFFECT_ALL, SPELL_EFFECT_ANY);
+ }
};
enum DivineStormSpell
@@ -1402,119 +1148,86 @@ enum DivineStormSpell
};
// 70769 Divine Storm!
-class spell_gen_divine_storm_cd_reset : public SpellScriptLoader
+class spell_gen_divine_storm_cd_reset : public SpellScript
{
- public:
- spell_gen_divine_storm_cd_reset() : SpellScriptLoader("spell_gen_divine_storm_cd_reset") { }
-
- class spell_gen_divine_storm_cd_reset_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_divine_storm_cd_reset_SpellScript);
-
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
+ PrepareSpellScript(spell_gen_divine_storm_cd_reset);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_DIVINE_STORM });
- }
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- void HandleScript(SpellEffIndex /*effIndex*/)
- {
- Player* caster = GetCaster()->ToPlayer();
- if (caster->GetSpellHistory()->HasCooldown(SPELL_DIVINE_STORM))
- caster->GetSpellHistory()->ResetCooldown(SPELL_DIVINE_STORM, true);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_DIVINE_STORM });
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_divine_storm_cd_reset_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Player* caster = GetCaster()->ToPlayer();
+ if (caster->GetSpellHistory()->HasCooldown(SPELL_DIVINE_STORM))
+ caster->GetSpellHistory()->ResetCooldown(SPELL_DIVINE_STORM, true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_divine_storm_cd_reset_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_divine_storm_cd_reset::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
-class spell_gen_ds_flush_knockback : public SpellScriptLoader
+class spell_gen_ds_flush_knockback : public SpellScript
{
- public:
- spell_gen_ds_flush_knockback() : SpellScriptLoader("spell_gen_ds_flush_knockback") { }
+ PrepareSpellScript(spell_gen_ds_flush_knockback);
- class spell_gen_ds_flush_knockback_SpellScript : public SpellScript
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ // Here the target is the water spout and determines the position where the player is knocked from
+ if (Unit* target = GetHitUnit())
{
- PrepareSpellScript(spell_gen_ds_flush_knockback_SpellScript);
-
- void HandleScript(SpellEffIndex /*effIndex*/)
- {
- // Here the target is the water spout and determines the position where the player is knocked from
- if (Unit* target = GetHitUnit())
- {
- if (Player* player = GetCaster()->ToPlayer())
- {
- float horizontalSpeed = 20.0f + (40.0f - GetCaster()->GetDistance(target));
- float verticalSpeed = 8.0f;
- // This method relies on the Dalaran Sewer map disposition and Water Spout position
- // What we do is knock the player from a position exactly behind him and at the end of the pipe
- player->KnockbackFrom(target->GetPositionX(), player->GetPositionY(), horizontalSpeed, verticalSpeed);
- }
- }
- }
-
- void Register() override
+ if (Player* player = GetCaster()->ToPlayer())
{
- OnEffectHitTarget += SpellEffectFn(spell_gen_ds_flush_knockback_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
+ float horizontalSpeed = 20.0f + (40.0f - GetCaster()->GetDistance(target));
+ float verticalSpeed = 8.0f;
+ // This method relies on the Dalaran Sewer map disposition and Water Spout position
+ // What we do is knock the player from a position exactly behind him and at the end of the pipe
+ player->KnockbackFrom(target->GetPositionX(), player->GetPositionY(), horizontalSpeed, verticalSpeed);
}
- };
-
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_ds_flush_knockback_SpellScript();
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_ds_flush_knockback::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
-class spell_gen_dungeon_credit : public SpellScriptLoader
+class spell_gen_dungeon_credit : public SpellScript
{
- public:
- spell_gen_dungeon_credit() : SpellScriptLoader("spell_gen_dungeon_credit") { }
+ PrepareSpellScript(spell_gen_dungeon_credit);
- class spell_gen_dungeon_credit_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_dungeon_credit_SpellScript);
-
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_UNIT;
- }
-
- void CreditEncounter()
- {
- // This hook is executed for every target, make sure we only credit instance once
- if (_handled)
- return;
-
- _handled = true;
- Unit* caster = GetCaster();
- if (InstanceScript* instance = caster->GetInstanceScript())
- instance->UpdateEncounterStateForSpellCast(GetSpellInfo()->Id, caster);
- }
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_UNIT;
+ }
- void Register() override
- {
- AfterHit += SpellHitFn(spell_gen_dungeon_credit_SpellScript::CreditEncounter);
- }
+ void CreditEncounter()
+ {
+ // This hook is executed for every target, make sure we only credit instance once
+ if (_handled)
+ return;
+
+ _handled = true;
+ Unit* caster = GetCaster();
+ if (InstanceScript* instance = caster->GetInstanceScript())
+ instance->UpdateEncounterStateForSpellCast(GetSpellInfo()->Id, caster);
+ }
- bool _handled = false;
- };
+ void Register() override
+ {
+ AfterHit += SpellHitFn(spell_gen_dungeon_credit::CreditEncounter);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_dungeon_credit_SpellScript();
- }
+ bool _handled = false;
};
enum EluneCandle
@@ -1530,65 +1243,54 @@ enum EluneCandle
SPELL_ELUNE_CANDLE_NORMAL = 26636
};
-class spell_gen_elune_candle : public SpellScriptLoader
+class spell_gen_elune_candle : public SpellScript
{
- public:
- spell_gen_elune_candle() : SpellScriptLoader("spell_gen_elune_candle") { }
+ PrepareSpellScript(spell_gen_elune_candle);
- class spell_gen_elune_candle_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_elune_candle_SpellScript);
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
+ {
+ SPELL_ELUNE_CANDLE_OMEN_HEAD,
+ SPELL_ELUNE_CANDLE_OMEN_CHEST,
+ SPELL_ELUNE_CANDLE_OMEN_HAND_R,
+ SPELL_ELUNE_CANDLE_OMEN_HAND_L,
+ SPELL_ELUNE_CANDLE_NORMAL
+ });
+ }
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_ELUNE_CANDLE_OMEN_HEAD,
- SPELL_ELUNE_CANDLE_OMEN_CHEST,
- SPELL_ELUNE_CANDLE_OMEN_HAND_R,
- SPELL_ELUNE_CANDLE_OMEN_HAND_L,
- SPELL_ELUNE_CANDLE_NORMAL
- });
- }
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ uint32 spellId = 0;
- void HandleScript(SpellEffIndex /*effIndex*/)
+ if (GetHitUnit()->GetEntry() == NPC_OMEN)
+ {
+ switch (urand(0, 3))
{
- uint32 spellId = 0;
-
- if (GetHitUnit()->GetEntry() == NPC_OMEN)
- {
- switch (urand(0, 3))
- {
- case 0:
- spellId = SPELL_ELUNE_CANDLE_OMEN_HEAD;
- break;
- case 1:
- spellId = SPELL_ELUNE_CANDLE_OMEN_CHEST;
- break;
- case 2:
- spellId = SPELL_ELUNE_CANDLE_OMEN_HAND_R;
- break;
- case 3:
- spellId = SPELL_ELUNE_CANDLE_OMEN_HAND_L;
- break;
- }
- }
- else
- spellId = SPELL_ELUNE_CANDLE_NORMAL;
-
- GetCaster()->CastSpell(GetHitUnit(), spellId, true, nullptr);
+ case 0:
+ spellId = SPELL_ELUNE_CANDLE_OMEN_HEAD;
+ break;
+ case 1:
+ spellId = SPELL_ELUNE_CANDLE_OMEN_CHEST;
+ break;
+ case 2:
+ spellId = SPELL_ELUNE_CANDLE_OMEN_HAND_R;
+ break;
+ case 3:
+ spellId = SPELL_ELUNE_CANDLE_OMEN_HAND_L;
+ break;
}
+ }
+ else
+ spellId = SPELL_ELUNE_CANDLE_NORMAL;
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_elune_candle_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ GetCaster()->CastSpell(GetHitUnit(), spellId, true, nullptr);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_elune_candle_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_elune_candle::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum TransporterBackfires
@@ -1598,100 +1300,78 @@ enum TransporterBackfires
SPELL_TRANSPORTER_MALFUNCTION_MISS = 36902
};
-class spell_gen_gadgetzan_transporter_backfire : public SpellScriptLoader
+class spell_gen_gadgetzan_transporter_backfire : public SpellScript
{
- public:
- spell_gen_gadgetzan_transporter_backfire() : SpellScriptLoader("spell_gen_gadgetzan_transporter_backfire") { }
+ PrepareSpellScript(spell_gen_gadgetzan_transporter_backfire);
- class spell_gen_gadgetzan_transporter_backfire_SpellScript : public SpellScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareSpellScript(spell_gen_gadgetzan_transporter_backfire_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_TRANSPORTER_MALFUNCTION_POLYMORPH,
- SPELL_TRANSPORTER_EVIL_TWIN,
- SPELL_TRANSPORTER_MALFUNCTION_MISS
- });
- }
-
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- Unit* caster = GetCaster();
- int32 r = irand(0, 119);
- if (r < 20) // Transporter Malfunction - 1/6 polymorph
- caster->CastSpell(caster, SPELL_TRANSPORTER_MALFUNCTION_POLYMORPH, true);
- else if (r < 100) // Evil Twin - 4/6 evil twin
- caster->CastSpell(caster, SPELL_TRANSPORTER_EVIL_TWIN, true);
- else // Transporter Malfunction - 1/6 miss the target
- caster->CastSpell(caster, SPELL_TRANSPORTER_MALFUNCTION_MISS, true);
- }
+ SPELL_TRANSPORTER_MALFUNCTION_POLYMORPH,
+ SPELL_TRANSPORTER_EVIL_TWIN,
+ SPELL_TRANSPORTER_MALFUNCTION_MISS
+ });
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_gadgetzan_transporter_backfire_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ Unit* caster = GetCaster();
+ int32 r = irand(0, 119);
+ if (r < 20) // Transporter Malfunction - 1/6 polymorph
+ caster->CastSpell(caster, SPELL_TRANSPORTER_MALFUNCTION_POLYMORPH, true);
+ else if (r < 100) // Evil Twin - 4/6 evil twin
+ caster->CastSpell(caster, SPELL_TRANSPORTER_EVIL_TWIN, true);
+ else // Transporter Malfunction - 1/6 miss the target
+ caster->CastSpell(caster, SPELL_TRANSPORTER_MALFUNCTION_MISS, true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_gadgetzan_transporter_backfire_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_gadgetzan_transporter_backfire::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
-class spell_gen_gift_of_naaru : public SpellScriptLoader
+class spell_gen_gift_of_naaru : public AuraScript
{
- public:
- spell_gen_gift_of_naaru() : SpellScriptLoader("spell_gen_gift_of_naaru") { }
-
- class spell_gen_gift_of_naaru_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_gift_of_naaru_AuraScript);
-
- void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/)
- {
- if (!GetCaster())
- return;
-
- float heal = 0.0f;
- switch (GetSpellInfo()->SpellFamilyName)
- {
- case SPELLFAMILY_MAGE:
- case SPELLFAMILY_WARLOCK:
- case SPELLFAMILY_PRIEST:
- heal = 1.885f * float(GetCaster()->SpellBaseDamageBonusDone(GetSpellInfo()->GetSchoolMask()));
- break;
- case SPELLFAMILY_PALADIN:
- case SPELLFAMILY_SHAMAN:
- heal = std::max(1.885f * float(GetCaster()->SpellBaseDamageBonusDone(GetSpellInfo()->GetSchoolMask())), 1.1f * float(GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK)));
- break;
- case SPELLFAMILY_WARRIOR:
- case SPELLFAMILY_HUNTER:
- case SPELLFAMILY_DEATHKNIGHT:
- heal = 1.1f * float(std::max(GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK), GetCaster()->GetTotalAttackPowerValue(RANGED_ATTACK)));
- break;
- case SPELLFAMILY_GENERIC:
- default:
- break;
- }
-
- int32 healTick = std::floor(heal / aurEff->GetTotalTicks());
- amount += int32(std::max(healTick, 0));
- }
+ PrepareAuraScript(spell_gen_gift_of_naaru);
- void Register() override
- {
- DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_gift_of_naaru_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_HEAL);
- }
- };
+ void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/)
+ {
+ if (!GetCaster())
+ return;
+
+ float heal = 0.0f;
+ switch (GetSpellInfo()->SpellFamilyName)
+ {
+ case SPELLFAMILY_MAGE:
+ case SPELLFAMILY_WARLOCK:
+ case SPELLFAMILY_PRIEST:
+ heal = 1.885f * float(GetCaster()->SpellBaseDamageBonusDone(GetSpellInfo()->GetSchoolMask()));
+ break;
+ case SPELLFAMILY_PALADIN:
+ case SPELLFAMILY_SHAMAN:
+ heal = std::max(1.885f * float(GetCaster()->SpellBaseDamageBonusDone(GetSpellInfo()->GetSchoolMask())), 1.1f * float(GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK)));
+ break;
+ case SPELLFAMILY_WARRIOR:
+ case SPELLFAMILY_HUNTER:
+ case SPELLFAMILY_DEATHKNIGHT:
+ heal = 1.1f * float(std::max(GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK), GetCaster()->GetTotalAttackPowerValue(RANGED_ATTACK)));
+ break;
+ case SPELLFAMILY_GENERIC:
+ default:
+ break;
+ }
+
+ int32 healTick = std::floor(heal / aurEff->GetTotalTicks());
+ amount += int32(std::max(healTick, 0));
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_gift_of_naaru_AuraScript();
- }
+ void Register() override
+ {
+ DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_gift_of_naaru::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_HEAL);
+ }
};
enum GnomishTransporter
@@ -1700,66 +1380,44 @@ enum GnomishTransporter
SPELL_TRANSPORTER_FAILURE = 23446
};
-class spell_gen_gnomish_transporter : public SpellScriptLoader
+class spell_gen_gnomish_transporter : public SpellScript
{
- public:
- spell_gen_gnomish_transporter() : SpellScriptLoader("spell_gen_gnomish_transporter") { }
+ PrepareSpellScript(spell_gen_gnomish_transporter);
- class spell_gen_gnomish_transporter_SpellScript : public SpellScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareSpellScript(spell_gen_gnomish_transporter_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_TRANSPORTER_SUCCESS,
- SPELL_TRANSPORTER_FAILURE
- });
- }
-
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- GetCaster()->CastSpell(GetCaster(), roll_chance_i(50) ? SPELL_TRANSPORTER_SUCCESS : SPELL_TRANSPORTER_FAILURE, true);
- }
+ SPELL_TRANSPORTER_SUCCESS,
+ SPELL_TRANSPORTER_FAILURE
+ });
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_gnomish_transporter_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ GetCaster()->CastSpell(GetCaster(), roll_chance_i(50) ? SPELL_TRANSPORTER_SUCCESS : SPELL_TRANSPORTER_FAILURE, true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_gnomish_transporter_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_gnomish_transporter::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
-class spell_gen_lifeblood : public SpellScriptLoader
+class spell_gen_lifeblood : public AuraScript
{
- public:
- spell_gen_lifeblood() : SpellScriptLoader("spell_gen_lifeblood") { }
-
- class spell_gen_lifeblood_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_lifeblood_AuraScript);
-
- void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/)
- {
- if (Unit* owner = GetUnitOwner())
- amount += int32(CalculatePct(owner->GetMaxHealth(), 1.5f / aurEff->GetTotalTicks()));
- }
+ PrepareAuraScript(spell_gen_lifeblood);
- void Register() override
- {
- DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_lifeblood_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_HEAL);
- }
- };
+ void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/)
+ {
+ if (Unit* owner = GetUnitOwner())
+ amount += int32(CalculatePct(owner->GetMaxHealth(), 1.5f / aurEff->GetTotalTicks()));
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_lifeblood_AuraScript();
- }
+ void Register() override
+ {
+ DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_lifeblood::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_HEAL);
+ }
};
enum GenericLifebloom
@@ -1791,7 +1449,7 @@ class spell_gen_lifebloom : public SpellScriptLoader
void AfterRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
- // Final heal only on duration end
+ // final heal only on duration end or dispel
if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE && GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_ENEMY_SPELL)
return;
@@ -1823,52 +1481,41 @@ enum MagicRoosterSpells
SPELL_MAGIC_ROOSTER_TAUREN_MALE = 66124
};
-class spell_gen_magic_rooster : public SpellScriptLoader
+class spell_gen_magic_rooster : public SpellScript
{
- public:
- spell_gen_magic_rooster() : SpellScriptLoader("spell_gen_magic_rooster") { }
+ PrepareSpellScript(spell_gen_magic_rooster);
- class spell_gen_magic_rooster_SpellScript : public SpellScript
+ void HandleScript(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ if (Player* target = GetHitPlayer())
{
- PrepareSpellScript(spell_gen_magic_rooster_SpellScript);
-
- void HandleScript(SpellEffIndex effIndex)
- {
- PreventHitDefaultEffect(effIndex);
- if (Player* target = GetHitPlayer())
- {
- // prevent client crashes from stacking mounts
- target->RemoveAurasByType(SPELL_AURA_MOUNTED);
-
- uint32 spellId = SPELL_MAGIC_ROOSTER_NORMAL;
- switch (target->getRace())
- {
- case RACE_DRAENEI:
- if (target->getGender() == GENDER_MALE)
- spellId = SPELL_MAGIC_ROOSTER_DRAENEI_MALE;
- break;
- case RACE_TAUREN:
- if (target->getGender() == GENDER_MALE)
- spellId = SPELL_MAGIC_ROOSTER_TAUREN_MALE;
- break;
- default:
- break;
- }
-
- target->CastSpell(target, spellId, true);
- }
- }
+ // prevent client crashes from stacking mounts
+ target->RemoveAurasByType(SPELL_AURA_MOUNTED);
- void Register() override
+ uint32 spellId = SPELL_MAGIC_ROOSTER_NORMAL;
+ switch (target->getRace())
{
- OnEffectHitTarget += SpellEffectFn(spell_gen_magic_rooster_SpellScript::HandleScript, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT);
+ case RACE_DRAENEI:
+ if (target->getGender() == GENDER_MALE)
+ spellId = SPELL_MAGIC_ROOSTER_DRAENEI_MALE;
+ break;
+ case RACE_TAUREN:
+ if (target->getGender() == GENDER_MALE)
+ spellId = SPELL_MAGIC_ROOSTER_TAUREN_MALE;
+ break;
+ default:
+ break;
}
- };
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_magic_rooster_SpellScript();
+ target->CastSpell(target, spellId, true);
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_magic_rooster::HandleScript, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
enum Mounts
@@ -2089,115 +1736,104 @@ enum ChargeSpells
SPELL_CHARGE_MISS_EFFECT = 62977,
};
-class spell_gen_mounted_charge: public SpellScriptLoader
+class spell_gen_mounted_charge : public SpellScript
{
- public:
- spell_gen_mounted_charge() : SpellScriptLoader("spell_gen_mounted_charge") { }
-
- class spell_gen_mounted_charge_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_mounted_charge_SpellScript);
-
- void HandleScriptEffect(SpellEffIndex effIndex)
- {
- Unit* target = GetHitUnit();
-
- switch (effIndex)
- {
- case EFFECT_0: // On spells wich trigger the damaging spell (and also the visual)
- {
- uint32 spellId;
-
- switch (GetSpellInfo()->Id)
- {
- case SPELL_CHARGE_TRIGGER_TRIAL_CHAMPION:
- spellId = SPELL_CHARGE_CHARGING_EFFECT_20K_1;
- break;
- case SPELL_CHARGE_TRIGGER_FACTION_MOUNTS:
- spellId = SPELL_CHARGE_CHARGING_EFFECT_8K5;
- break;
- default:
- return;
- }
-
- // If target isn't a training dummy there's a chance of failing the charge
- if (!target->IsCharmedOwnedByPlayerOrPlayer() && roll_chance_f(12.5f))
- spellId = SPELL_CHARGE_MISS_EFFECT;
+ PrepareSpellScript(spell_gen_mounted_charge);
- if (Unit* vehicle = GetCaster()->GetVehicleBase())
- vehicle->CastSpell(target, spellId, false);
- else
- GetCaster()->CastSpell(target, spellId, false);
- break;
- }
- case EFFECT_1: // On damaging spells, for removing a defend layer
- case EFFECT_2:
- {
- Unit::AuraApplicationMap const& auras = target->GetAppliedAuras();
- for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
- {
- if (Aura* aura = itr->second->GetBase())
- {
- SpellInfo const* auraInfo = aura->GetSpellInfo();
- if (auraInfo && auraInfo->SpellIconID == 2007 && aura->HasEffectType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN))
- {
- aura->ModStackAmount(-1, AURA_REMOVE_BY_ENEMY_SPELL);
- // Remove dummys from rider (Necessary for updating visual shields)
- if (Unit* rider = target->GetCharmer())
- if (Aura* defend = rider->GetAura(aura->GetId()))
- defend->ModStackAmount(-1, AURA_REMOVE_BY_ENEMY_SPELL);
- break;
- }
- }
- }
- break;
- }
- }
- }
+ void HandleScriptEffect(SpellEffIndex effIndex)
+ {
+ Unit* target = GetHitUnit();
- void HandleChargeEffect(SpellEffIndex /*effIndex*/)
+ switch (effIndex)
+ {
+ case EFFECT_0: // On spells wich trigger the damaging spell (and also the visual)
{
uint32 spellId;
switch (GetSpellInfo()->Id)
{
- case SPELL_CHARGE_CHARGING_EFFECT_8K5:
- spellId = SPELL_CHARGE_DAMAGE_8K5;
- break;
- case SPELL_CHARGE_CHARGING_EFFECT_20K_1:
- case SPELL_CHARGE_CHARGING_EFFECT_20K_2:
- spellId = SPELL_CHARGE_DAMAGE_20K;
+ case SPELL_CHARGE_TRIGGER_TRIAL_CHAMPION:
+ spellId = SPELL_CHARGE_CHARGING_EFFECT_20K_1;
break;
- case SPELL_CHARGE_CHARGING_EFFECT_45K_1:
- case SPELL_CHARGE_CHARGING_EFFECT_45K_2:
- spellId = SPELL_CHARGE_DAMAGE_45K;
+ case SPELL_CHARGE_TRIGGER_FACTION_MOUNTS:
+ spellId = SPELL_CHARGE_CHARGING_EFFECT_8K5;
break;
default:
return;
}
- if (Unit* rider = GetCaster()->GetCharmer())
- rider->CastSpell(GetHitUnit(), spellId, false);
+ // If target isn't a training dummy there's a chance of failing the charge
+ if (!target->IsCharmedOwnedByPlayerOrPlayer() && roll_chance_f(12.5f))
+ spellId = SPELL_CHARGE_MISS_EFFECT;
+
+ if (Unit* vehicle = GetCaster()->GetVehicleBase())
+ vehicle->CastSpell(target, spellId, false);
else
- GetCaster()->CastSpell(GetHitUnit(), spellId, false);
+ GetCaster()->CastSpell(target, spellId, false);
+ break;
}
-
- void Register() override
+ case EFFECT_1: // On damaging spells, for removing a defend layer
+ case EFFECT_2:
{
- SpellInfo const* spell = sSpellMgr->AssertSpellInfo(m_scriptSpellId);
-
- if (spell->HasEffect(SPELL_EFFECT_SCRIPT_EFFECT))
- OnEffectHitTarget += SpellEffectFn(spell_gen_mounted_charge_SpellScript::HandleScriptEffect, EFFECT_FIRST_FOUND, SPELL_EFFECT_SCRIPT_EFFECT);
-
- if (spell->Effects[EFFECT_0].Effect == SPELL_EFFECT_CHARGE)
- OnEffectHitTarget += SpellEffectFn(spell_gen_mounted_charge_SpellScript::HandleChargeEffect, EFFECT_0, SPELL_EFFECT_CHARGE);
+ Unit::AuraApplicationMap const& auras = target->GetAppliedAuras();
+ for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
+ {
+ if (Aura* aura = itr->second->GetBase())
+ {
+ SpellInfo const* auraInfo = aura->GetSpellInfo();
+ if (auraInfo && auraInfo->SpellIconID == 2007 && aura->HasEffectType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN))
+ {
+ aura->ModStackAmount(-1, AURA_REMOVE_BY_ENEMY_SPELL);
+ // Remove dummys from rider (Necessary for updating visual shields)
+ if (Unit* rider = target->GetCharmer())
+ if (Aura* defend = rider->GetAura(aura->GetId()))
+ defend->ModStackAmount(-1, AURA_REMOVE_BY_ENEMY_SPELL);
+ break;
+ }
+ }
+ }
+ break;
}
- };
+ }
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_mounted_charge_SpellScript();
+ void HandleChargeEffect(SpellEffIndex /*effIndex*/)
+ {
+ uint32 spellId;
+
+ switch (GetSpellInfo()->Id)
+ {
+ case SPELL_CHARGE_CHARGING_EFFECT_8K5:
+ spellId = SPELL_CHARGE_DAMAGE_8K5;
+ break;
+ case SPELL_CHARGE_CHARGING_EFFECT_20K_1:
+ case SPELL_CHARGE_CHARGING_EFFECT_20K_2:
+ spellId = SPELL_CHARGE_DAMAGE_20K;
+ break;
+ case SPELL_CHARGE_CHARGING_EFFECT_45K_1:
+ case SPELL_CHARGE_CHARGING_EFFECT_45K_2:
+ spellId = SPELL_CHARGE_DAMAGE_45K;
+ break;
+ default:
+ return;
}
+
+ if (Unit* rider = GetCaster()->GetCharmer())
+ rider->CastSpell(GetHitUnit(), spellId, false);
+ else
+ GetCaster()->CastSpell(GetHitUnit(), spellId, false);
+ }
+
+ void Register() override
+ {
+ SpellInfo const* spell = sSpellMgr->AssertSpellInfo(m_scriptSpellId);
+
+ if (spell->HasEffect(SPELL_EFFECT_SCRIPT_EFFECT))
+ OnEffectHitTarget += SpellEffectFn(spell_gen_mounted_charge::HandleScriptEffect, EFFECT_FIRST_FOUND, SPELL_EFFECT_SCRIPT_EFFECT);
+
+ if (spell->Effects[EFFECT_0].Effect == SPELL_EFFECT_CHARGE)
+ OnEffectHitTarget += SpellEffectFn(spell_gen_mounted_charge::HandleChargeEffect, EFFECT_0, SPELL_EFFECT_CHARGE);
+ }
};
enum MossCoveredFeet
@@ -2207,36 +1843,25 @@ enum MossCoveredFeet
// 6870 Moss Covered Feet
// 31399 Moss Covered Feet
-class spell_gen_moss_covered_feet : public SpellScriptLoader
+class spell_gen_moss_covered_feet : public AuraScript
{
- public:
- spell_gen_moss_covered_feet() : SpellScriptLoader("spell_gen_moss_covered_feet") { }
-
- class spell_gen_moss_covered_feet_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_moss_covered_feet_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_FALL_DOWN });
- }
+ PrepareAuraScript(spell_gen_moss_covered_feet);
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
- eventInfo.GetActionTarget()->CastSpell((Unit*)nullptr, SPELL_FALL_DOWN, true, nullptr, aurEff);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_FALL_DOWN });
+ }
- void Register() override
- {
- OnEffectProc += AuraEffectProcFn(spell_gen_moss_covered_feet_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
- }
- };
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+ eventInfo.GetActionTarget()->CastSpell(nullptr, SPELL_FALL_DOWN, true, nullptr, aurEff);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_moss_covered_feet_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_gen_moss_covered_feet::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
+ }
};
enum Netherbloom : uint32
@@ -2245,57 +1870,46 @@ enum Netherbloom : uint32
};
// 28702 - Netherbloom
-class spell_gen_netherbloom : public SpellScriptLoader
+class spell_gen_netherbloom : public SpellScript
{
- public:
- spell_gen_netherbloom() : SpellScriptLoader("spell_gen_netherbloom") { }
-
- class spell_gen_netherbloom_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_netherbloom_SpellScript);
+ PrepareSpellScript(spell_gen_netherbloom);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- for (uint8 i = 0; i < 5; ++i)
- if (!ValidateSpellInfo({ SPELL_NETHERBLOOM_POLLEN_1 + i }))
- return false;
-
- return true;
- }
-
- void HandleScript(SpellEffIndex effIndex)
- {
- PreventHitDefaultEffect(effIndex);
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ for (uint8 i = 0; i < 5; ++i)
+ if (!ValidateSpellInfo({ SPELL_NETHERBLOOM_POLLEN_1 + i }))
+ return false;
- if (Unit* target = GetHitUnit())
- {
- // 25% chance of casting a random buff
- if (roll_chance_i(75))
- return;
+ return true;
+ }
- // triggered spells are 28703 to 28707
- // Note: some sources say, that there was the possibility of
- // receiving a debuff. However, this seems to be removed by a patch.
+ void HandleScript(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
- // don't overwrite an existing aura
- for (uint8 i = 0; i < 5; ++i)
- if (target->HasAura(SPELL_NETHERBLOOM_POLLEN_1 + i))
- return;
+ if (Unit* target = GetHitUnit())
+ {
+ // 25% chance of casting a random buff
+ if (roll_chance_i(75))
+ return;
- target->CastSpell(target, SPELL_NETHERBLOOM_POLLEN_1 + urand(0, 4), true);
- }
- }
+ // triggered spells are 28703 to 28707
+ // Note: some sources say, that there was the possibility of
+ // receiving a debuff. However, this seems to be removed by a patch.
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_netherbloom_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ // don't overwrite an existing aura
+ for (uint8 i = 0; i < 5; ++i)
+ if (target->HasAura(SPELL_NETHERBLOOM_POLLEN_1 + i))
+ return;
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_netherbloom_SpellScript();
+ target->CastSpell(target, SPELL_NETHERBLOOM_POLLEN_1 + urand(0, 4), true);
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_netherbloom::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
enum NightmareVine
@@ -2304,42 +1918,31 @@ enum NightmareVine
};
// 28720 - Nightmare Vine
-class spell_gen_nightmare_vine : public SpellScriptLoader
+class spell_gen_nightmare_vine : public SpellScript
{
- public:
- spell_gen_nightmare_vine() : SpellScriptLoader("spell_gen_nightmare_vine") { }
-
- class spell_gen_nightmare_vine_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_nightmare_vine_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_NIGHTMARE_POLLEN });
- }
+ PrepareSpellScript(spell_gen_nightmare_vine);
- void HandleScript(SpellEffIndex effIndex)
- {
- PreventHitDefaultEffect(effIndex);
-
- if (Unit* target = GetHitUnit())
- {
- // 25% chance of casting Nightmare Pollen
- if (roll_chance_i(25))
- target->CastSpell(target, SPELL_NIGHTMARE_POLLEN, true);
- }
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_NIGHTMARE_POLLEN });
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_nightmare_vine_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ void HandleScript(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
- SpellScript* GetSpellScript() const override
+ if (Unit* target = GetHitUnit())
{
- return new spell_gen_nightmare_vine_SpellScript();
+ // 25% chance of casting Nightmare Pollen
+ if (roll_chance_i(25))
+ target->CastSpell(target, SPELL_NIGHTMARE_POLLEN, true);
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_nightmare_vine::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
enum ObsidianArmor
@@ -2353,126 +1956,104 @@ enum ObsidianArmor
};
// 27539 - Obsidian Armor
-class spell_gen_obsidian_armor : public SpellScriptLoader
+class spell_gen_obsidian_armor : public AuraScript
{
- public:
- spell_gen_obsidian_armor() : SpellScriptLoader("spell_gen_obsidian_armor") { }
-
- class spell_gen_obsidian_armor_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_obsidian_armor_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_GEN_OBSIDIAN_ARMOR_HOLY,
- SPELL_GEN_OBSIDIAN_ARMOR_FIRE,
- SPELL_GEN_OBSIDIAN_ARMOR_NATURE,
- SPELL_GEN_OBSIDIAN_ARMOR_FROST,
- SPELL_GEN_OBSIDIAN_ARMOR_SHADOW,
- SPELL_GEN_OBSIDIAN_ARMOR_ARCANE
- });
- }
-
- bool CheckProc(ProcEventInfo& eventInfo)
- {
- DamageInfo* damageInfo = eventInfo.GetDamageInfo();
- if (!damageInfo || !damageInfo->GetSpellInfo())
- return false;
-
- if (GetFirstSchoolInMask(eventInfo.GetSchoolMask()) == SPELL_SCHOOL_NORMAL)
- return false;
+ PrepareAuraScript(spell_gen_obsidian_armor);
- return true;
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
+ {
+ SPELL_GEN_OBSIDIAN_ARMOR_HOLY,
+ SPELL_GEN_OBSIDIAN_ARMOR_FIRE,
+ SPELL_GEN_OBSIDIAN_ARMOR_NATURE,
+ SPELL_GEN_OBSIDIAN_ARMOR_FROST,
+ SPELL_GEN_OBSIDIAN_ARMOR_SHADOW,
+ SPELL_GEN_OBSIDIAN_ARMOR_ARCANE
+ });
+ }
- void OnProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
+ bool CheckProc(ProcEventInfo& eventInfo)
+ {
+ DamageInfo* damageInfo = eventInfo.GetDamageInfo();
+ if (!damageInfo || !damageInfo->GetSpellInfo())
+ return false;
- uint32 spellId = 0;
- switch (GetFirstSchoolInMask(eventInfo.GetSchoolMask()))
- {
- case SPELL_SCHOOL_HOLY:
- spellId = SPELL_GEN_OBSIDIAN_ARMOR_HOLY;
- break;
- case SPELL_SCHOOL_FIRE:
- spellId = SPELL_GEN_OBSIDIAN_ARMOR_FIRE;
- break;
- case SPELL_SCHOOL_NATURE:
- spellId = SPELL_GEN_OBSIDIAN_ARMOR_NATURE;
- break;
- case SPELL_SCHOOL_FROST:
- spellId = SPELL_GEN_OBSIDIAN_ARMOR_FROST;
- break;
- case SPELL_SCHOOL_SHADOW:
- spellId = SPELL_GEN_OBSIDIAN_ARMOR_SHADOW;
- break;
- case SPELL_SCHOOL_ARCANE:
- spellId = SPELL_GEN_OBSIDIAN_ARMOR_ARCANE;
- break;
- default:
- return;
- }
- GetTarget()->CastSpell(GetTarget(), spellId, true, nullptr, aurEff);
- }
+ if (GetFirstSchoolInMask(eventInfo.GetSchoolMask()) == SPELL_SCHOOL_NORMAL)
+ return false;
- void Register() override
- {
- DoCheckProc += AuraCheckProcFn(spell_gen_obsidian_armor_AuraScript::CheckProc);
- OnEffectProc += AuraEffectProcFn(spell_gen_obsidian_armor_AuraScript::OnProc, EFFECT_0, SPELL_AURA_DUMMY);
- }
- };
+ return true;
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_obsidian_armor_AuraScript();
+ void OnProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+
+ uint32 spellId = 0;
+ switch (GetFirstSchoolInMask(eventInfo.GetSchoolMask()))
+ {
+ case SPELL_SCHOOL_HOLY:
+ spellId = SPELL_GEN_OBSIDIAN_ARMOR_HOLY;
+ break;
+ case SPELL_SCHOOL_FIRE:
+ spellId = SPELL_GEN_OBSIDIAN_ARMOR_FIRE;
+ break;
+ case SPELL_SCHOOL_NATURE:
+ spellId = SPELL_GEN_OBSIDIAN_ARMOR_NATURE;
+ break;
+ case SPELL_SCHOOL_FROST:
+ spellId = SPELL_GEN_OBSIDIAN_ARMOR_FROST;
+ break;
+ case SPELL_SCHOOL_SHADOW:
+ spellId = SPELL_GEN_OBSIDIAN_ARMOR_SHADOW;
+ break;
+ case SPELL_SCHOOL_ARCANE:
+ spellId = SPELL_GEN_OBSIDIAN_ARMOR_ARCANE;
+ break;
+ default:
+ return;
}
+ GetTarget()->CastSpell(GetTarget(), spellId, true, nullptr, aurEff);
+ }
+
+ void Register() override
+ {
+ DoCheckProc += AuraCheckProcFn(spell_gen_obsidian_armor::CheckProc);
+ OnEffectProc += AuraEffectProcFn(spell_gen_obsidian_armor::OnProc, EFFECT_0, SPELL_AURA_DUMMY);
+ }
};
-class spell_gen_oracle_wolvar_reputation : public SpellScriptLoader
+class spell_gen_oracle_wolvar_reputation : public SpellScript
{
- public:
- spell_gen_oracle_wolvar_reputation() : SpellScriptLoader("spell_gen_oracle_wolvar_reputation") { }
-
- class spell_gen_oracle_wolvar_reputation_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_oracle_wolvar_reputation_SpellScript);
-
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
+ PrepareSpellScript(spell_gen_oracle_wolvar_reputation);
- void HandleDummy(SpellEffIndex effIndex)
- {
- Player* player = GetCaster()->ToPlayer();
- uint32 factionId = GetSpellInfo()->Effects[effIndex].CalcValue();
- int32 repChange = GetSpellInfo()->Effects[EFFECT_1].CalcValue();
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionId);
- if (!factionEntry)
- return;
+ void HandleDummy(SpellEffIndex effIndex)
+ {
+ Player* player = GetCaster()->ToPlayer();
+ uint32 factionId = GetSpellInfo()->Effects[effIndex].CalcValue();
+ int32 repChange = GetSpellInfo()->Effects[EFFECT_1].CalcValue();
- // Set rep to baserep + basepoints (expecting spillover for oposite faction -> become hated)
- // Not when player already has equal or higher rep with this faction
- if (player->GetReputationMgr().GetReputation(factionEntry) < repChange)
- player->GetReputationMgr().SetReputation(factionEntry, repChange);
+ FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionId);
+ if (!factionEntry)
+ return;
- // EFFECT_INDEX_2 most likely update at war state, we already handle this in SetReputation
- }
+ // Set rep to baserep + basepoints (expecting spillover for oposite faction -> become hated)
+ // Not when player already has equal or higher rep with this faction
+ if (player->GetReputationMgr().GetReputation(factionEntry) < repChange)
+ player->GetReputationMgr().SetReputation(factionEntry, repChange);
- void Register() override
- {
- OnEffectHit += SpellEffectFn(spell_gen_oracle_wolvar_reputation_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ // EFFECT_INDEX_2 most likely update at war state, we already handle this in SetReputation
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_oracle_wolvar_reputation_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHit += SpellEffectFn(spell_gen_oracle_wolvar_reputation::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum OrcDisguiseSpells
@@ -2482,48 +2063,37 @@ enum OrcDisguiseSpells
SPELL_ORC_DISGUISE_FEMALE = 45762
};
-class spell_gen_orc_disguise : public SpellScriptLoader
+class spell_gen_orc_disguise : public SpellScript
{
- public:
- spell_gen_orc_disguise() : SpellScriptLoader("spell_gen_orc_disguise") { }
+ PrepareSpellScript(spell_gen_orc_disguise);
- class spell_gen_orc_disguise_SpellScript : public SpellScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareSpellScript(spell_gen_orc_disguise_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_ORC_DISGUISE_TRIGGER,
- SPELL_ORC_DISGUISE_MALE,
- SPELL_ORC_DISGUISE_FEMALE
- });
- }
-
- void HandleScript(SpellEffIndex /*effIndex*/)
- {
- Unit* caster = GetCaster();
- if (Player* target = GetHitPlayer())
- {
- uint8 gender = target->getGender();
- if (!gender)
- caster->CastSpell(target, SPELL_ORC_DISGUISE_MALE, true);
- else
- caster->CastSpell(target, SPELL_ORC_DISGUISE_FEMALE, true);
- }
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_orc_disguise_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ SPELL_ORC_DISGUISE_TRIGGER,
+ SPELL_ORC_DISGUISE_MALE,
+ SPELL_ORC_DISGUISE_FEMALE
+ });
+ }
- SpellScript* GetSpellScript() const override
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ if (Player* target = GetHitPlayer())
{
- return new spell_gen_orc_disguise_SpellScript();
+ uint8 gender = target->getGender();
+ if (!gender)
+ caster->CastSpell(target, SPELL_ORC_DISGUISE_MALE, true);
+ else
+ caster->CastSpell(target, SPELL_ORC_DISGUISE_FEMALE, true);
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_orc_disguise::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
enum ParalyticPoison
@@ -2532,38 +2102,27 @@ enum ParalyticPoison
};
// 35201 - Paralytic Poison
-class spell_gen_paralytic_poison : public SpellScriptLoader
+class spell_gen_paralytic_poison : public AuraScript
{
- public:
- spell_gen_paralytic_poison() : SpellScriptLoader("spell_gen_paralytic_poison") { }
-
- class spell_gen_paralytic_poison_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_paralytic_poison_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_PARALYSIS });
- }
+ PrepareAuraScript(spell_gen_paralytic_poison);
- void HandleStun(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
- {
- if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE)
- return;
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_PARALYSIS });
+ }
- GetTarget()->CastSpell((Unit*)nullptr, SPELL_PARALYSIS, true, nullptr, aurEff);
- }
+ void HandleStun(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE)
+ return;
- void Register() override
- {
- AfterEffectRemove += AuraEffectRemoveFn(spell_gen_paralytic_poison_AuraScript::HandleStun, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
- }
- };
+ GetTarget()->CastSpell(nullptr, SPELL_PARALYSIS, true, nullptr, aurEff);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_paralytic_poison_AuraScript();
- }
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_gen_paralytic_poison::HandleStun, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
+ }
};
class spell_gen_proc_below_pct_damaged : public SpellScriptLoader
@@ -2601,30 +2160,19 @@ class spell_gen_proc_below_pct_damaged : public SpellScriptLoader
}
};
-class spell_gen_proc_charge_drop_only : public SpellScriptLoader
+class spell_gen_proc_charge_drop_only : public AuraScript
{
- public:
- spell_gen_proc_charge_drop_only() : SpellScriptLoader("spell_gen_proc_charge_drop_only") { }
-
- class spell_gen_proc_charge_drop_only_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_proc_charge_drop_only_AuraScript);
+ PrepareAuraScript(spell_gen_proc_charge_drop_only);
- void HandleChargeDrop(ProcEventInfo& /*eventInfo*/)
- {
- PreventDefaultAction();
- }
-
- void Register() override
- {
- OnProc += AuraProcFn(spell_gen_proc_charge_drop_only_AuraScript::HandleChargeDrop);
- }
- };
+ void HandleChargeDrop(ProcEventInfo& /*eventInfo*/)
+ {
+ PreventDefaultAction();
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_proc_charge_drop_only_AuraScript();
- }
+ void Register() override
+ {
+ OnProc += AuraProcFn(spell_gen_proc_charge_drop_only::HandleChargeDrop);
+ }
};
enum ParachuteSpells
@@ -2634,44 +2182,33 @@ enum ParachuteSpells
};
// 45472 Parachute
-class spell_gen_parachute : public SpellScriptLoader
+class spell_gen_parachute : public AuraScript
{
- public:
- spell_gen_parachute() : SpellScriptLoader("spell_gen_parachute") { }
+ PrepareAuraScript(spell_gen_parachute);
- class spell_gen_parachute_AuraScript : public AuraScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareAuraScript(spell_gen_parachute_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_PARACHUTE,
- SPELL_PARACHUTE_BUFF
- });
- }
-
- void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
- {
- if (Player* target = GetTarget()->ToPlayer())
- if (target->IsFalling())
- {
- target->RemoveAurasDueToSpell(SPELL_PARACHUTE);
- target->CastSpell(target, SPELL_PARACHUTE_BUFF, true);
- }
- }
+ SPELL_PARACHUTE,
+ SPELL_PARACHUTE_BUFF
+ });
+ }
- void Register() override
+ void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
+ {
+ if (Player* target = GetTarget()->ToPlayer())
+ if (target->IsFalling())
{
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_gen_parachute_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ target->RemoveAurasDueToSpell(SPELL_PARACHUTE);
+ target->CastSpell(target, SPELL_PARACHUTE_BUFF, true);
}
- };
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_parachute_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_gen_parachute::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
};
enum PetSummoned
@@ -2681,141 +2218,108 @@ enum PetSummoned
NPC_IMP = 416
};
-class spell_gen_pet_summoned : public SpellScriptLoader
+class spell_gen_pet_summoned : public SpellScript
{
- public:
- spell_gen_pet_summoned() : SpellScriptLoader("spell_gen_pet_summoned") { }
-
- class spell_gen_pet_summoned_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_pet_summoned_SpellScript);
+ PrepareSpellScript(spell_gen_pet_summoned);
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- void HandleScript(SpellEffIndex /*effIndex*/)
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Player* player = GetCaster()->ToPlayer();
+ if (player->GetLastPetNumber())
+ {
+ PetType newPetType = (player->getClass() == CLASS_HUNTER) ? HUNTER_PET : SUMMON_PET;
+ Pet* newPet = new Pet(player, newPetType);
+ if (newPet->LoadPetFromDB(player, 0, player->GetLastPetNumber(), true))
{
- Player* player = GetCaster()->ToPlayer();
- if (player->GetLastPetNumber())
- {
- PetType newPetType = (player->getClass() == CLASS_HUNTER) ? HUNTER_PET : SUMMON_PET;
- Pet* newPet = new Pet(player, newPetType);
- if (newPet->LoadPetFromDB(player, 0, player->GetLastPetNumber(), true))
- {
- // revive the pet if it is dead
- if (newPet->getDeathState() == DEAD)
- newPet->setDeathState(ALIVE);
+ // revive the pet if it is dead
+ if (newPet->getDeathState() == DEAD)
+ newPet->setDeathState(ALIVE);
- newPet->SetFullHealth();
- newPet->SetPower(newPet->getPowerType(), newPet->GetMaxPower(newPet->getPowerType()));
+ newPet->SetFullHealth();
+ newPet->SetPower(newPet->getPowerType(), newPet->GetMaxPower(newPet->getPowerType()));
- switch (newPet->GetEntry())
- {
- case NPC_DOOMGUARD:
- case NPC_INFERNAL:
- newPet->SetEntry(NPC_IMP);
- break;
- default:
- break;
- }
- }
- else
- delete newPet;
+ switch (newPet->GetEntry())
+ {
+ case NPC_DOOMGUARD:
+ case NPC_INFERNAL:
+ newPet->SetEntry(NPC_IMP);
+ break;
+ default:
+ break;
}
}
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_pet_summoned_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
-
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_pet_summoned_SpellScript();
+ else
+ delete newPet;
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_pet_summoned::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
-class spell_gen_profession_research : public SpellScriptLoader
+class spell_gen_profession_research : public SpellScript
{
- public:
- spell_gen_profession_research() : SpellScriptLoader("spell_gen_profession_research") { }
+ PrepareSpellScript(spell_gen_profession_research);
- class spell_gen_profession_research_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_profession_research_SpellScript);
-
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
-
- SpellCastResult CheckRequirement()
- {
- if (HasDiscoveredAllSpells(GetSpellInfo()->Id, GetCaster()->ToPlayer()))
- {
- SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_NOTHING_TO_DISCOVER);
- return SPELL_FAILED_CUSTOM_ERROR;
- }
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- return SPELL_CAST_OK;
- }
+ SpellCastResult CheckRequirement()
+ {
+ if (HasDiscoveredAllSpells(GetSpellInfo()->Id, GetCaster()->ToPlayer()))
+ {
+ SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_NOTHING_TO_DISCOVER);
+ return SPELL_FAILED_CUSTOM_ERROR;
+ }
- void HandleScript(SpellEffIndex /*effIndex*/)
- {
- Player* caster = GetCaster()->ToPlayer();
- uint32 spellId = GetSpellInfo()->Id;
+ return SPELL_CAST_OK;
+ }
- // learn random explicit discovery recipe (if any)
- if (uint32 discoveredSpellId = GetExplicitDiscoverySpell(spellId, caster))
- caster->LearnSpell(discoveredSpellId, false);
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Player* caster = GetCaster()->ToPlayer();
+ uint32 spellId = GetSpellInfo()->Id;
- caster->UpdateCraftSkill(spellId);
- }
+ // learn random explicit discovery recipe (if any)
+ if (uint32 discoveredSpellId = GetExplicitDiscoverySpell(spellId, caster))
+ caster->LearnSpell(discoveredSpellId, false);
- void Register() override
- {
- OnCheckCast += SpellCheckCastFn(spell_gen_profession_research_SpellScript::CheckRequirement);
- OnEffectHitTarget += SpellEffectFn(spell_gen_profession_research_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ caster->UpdateCraftSkill(spellId);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_profession_research_SpellScript();
- }
+ void Register() override
+ {
+ OnCheckCast += SpellCheckCastFn(spell_gen_profession_research::CheckRequirement);
+ OnEffectHitTarget += SpellEffectFn(spell_gen_profession_research::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
-class spell_gen_remove_flight_auras : public SpellScriptLoader
+class spell_gen_remove_flight_auras : public SpellScript
{
- public:
- spell_gen_remove_flight_auras() : SpellScriptLoader("spell_gen_remove_flight_auras") { }
-
- class spell_gen_remove_flight_auras_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_remove_flight_auras_SpellScript);
-
- void HandleScript(SpellEffIndex /*effIndex*/)
- {
- if (Unit* target = GetHitUnit())
- {
- target->RemoveAurasByType(SPELL_AURA_FLY);
- target->RemoveAurasByType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED);
- }
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_remove_flight_auras_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ PrepareSpellScript(spell_gen_remove_flight_auras);
- SpellScript* GetSpellScript() const override
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
{
- return new spell_gen_remove_flight_auras_SpellScript();
+ target->RemoveAurasByType(SPELL_AURA_FLY);
+ target->RemoveAurasByType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED);
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_remove_flight_auras::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
enum Replenishment
@@ -2836,84 +2340,68 @@ public:
}
};
-class spell_gen_replenishment : public SpellScriptLoader
+class spell_gen_replenishment : public SpellScript
{
- public:
- spell_gen_replenishment() : SpellScriptLoader("spell_gen_replenishment") { }
+ PrepareSpellScript(spell_gen_replenishment);
- class spell_gen_replenishment_SpellScript : public SpellScript
+ void RemoveInvalidTargets(std::list<WorldObject*>& targets)
+ {
+ // In arenas Replenishment may only affect the caster
+ if (Player* caster = GetCaster()->ToPlayer())
{
- PrepareSpellScript(spell_gen_replenishment_SpellScript);
-
- void RemoveInvalidTargets(std::list<WorldObject*>& targets)
+ if (caster->InArena())
{
- // In arenas Replenishment may only affect the caster
- if (Player* caster = GetCaster()->ToPlayer())
- {
- if (caster->InArena())
- {
- targets.clear();
- targets.push_back(caster);
- return;
- }
- }
-
- targets.remove_if(ReplenishmentCheck());
-
- uint8 const maxTargets = 10;
-
- if (targets.size() > maxTargets)
- {
- targets.sort(Trinity::PowerPctOrderPred(POWER_MANA));
- targets.resize(maxTargets);
- }
+ targets.clear();
+ targets.push_back(caster);
+ return;
}
+ }
- void Register() override
- {
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_gen_replenishment_SpellScript::RemoveInvalidTargets, EFFECT_ALL, TARGET_UNIT_CASTER_AREA_RAID);
- }
- };
+ targets.remove_if(ReplenishmentCheck());
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_replenishment_SpellScript();
- }
+ uint8 const maxTargets = 10;
- class spell_gen_replenishment_AuraScript : public AuraScript
+ if (targets.size() > maxTargets)
{
- PrepareAuraScript(spell_gen_replenishment_AuraScript);
+ targets.sort(Trinity::PowerPctOrderPred(POWER_MANA));
+ targets.resize(maxTargets);
+ }
+ }
- bool Load() override
- {
- return GetUnitOwner()->getPowerType() == POWER_MANA;
- }
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_gen_replenishment::RemoveInvalidTargets, EFFECT_ALL, TARGET_UNIT_CASTER_AREA_RAID);
+ }
+};
- void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
- {
- switch (GetSpellInfo()->Id)
- {
- case SPELL_REPLENISHMENT:
- amount = GetUnitOwner()->GetMaxPower(POWER_MANA) * 0.002f;
- break;
- case SPELL_INFINITE_REPLENISHMENT:
- amount = GetUnitOwner()->GetMaxPower(POWER_MANA) * 0.0025f;
- break;
- default:
- break;
- }
- }
+class spell_gen_replenishment_aura : public AuraScript
+{
+ PrepareAuraScript(spell_gen_replenishment_aura);
- void Register() override
- {
- DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_replenishment_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_ENERGIZE);
- }
- };
+ bool Load() override
+ {
+ return GetUnitOwner()->getPowerType() == POWER_MANA;
+ }
- AuraScript* GetAuraScript() const override
+ void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
+ {
+ switch (GetSpellInfo()->Id)
{
- return new spell_gen_replenishment_AuraScript();
+ case SPELL_REPLENISHMENT:
+ amount = GetUnitOwner()->GetMaxPower(POWER_MANA) * 0.002f;
+ break;
+ case SPELL_INFINITE_REPLENISHMENT:
+ amount = GetUnitOwner()->GetMaxPower(POWER_MANA) * 0.0025f;
+ break;
+ default:
+ break;
}
+ }
+
+ void Register() override
+ {
+ DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_replenishment_aura::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_ENERGIZE);
+ }
};
enum SeaforiumSpells
@@ -2921,45 +2409,34 @@ enum SeaforiumSpells
SPELL_PLANT_CHARGES_CREDIT_ACHIEVEMENT = 60937
};
-class spell_gen_seaforium_blast : public SpellScriptLoader
+class spell_gen_seaforium_blast : public SpellScript
{
- public:
- spell_gen_seaforium_blast() : SpellScriptLoader("spell_gen_seaforium_blast") { }
-
- class spell_gen_seaforium_blast_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_seaforium_blast_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_PLANT_CHARGES_CREDIT_ACHIEVEMENT });
- }
+ PrepareSpellScript(spell_gen_seaforium_blast);
- bool Load() override
- {
- // OriginalCaster is always available in Spell::prepare
- return GetOriginalCaster()->GetTypeId() == TYPEID_PLAYER;
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_PLANT_CHARGES_CREDIT_ACHIEVEMENT });
+ }
- void AchievementCredit(SpellEffIndex /*effIndex*/)
- {
- // but in effect handling OriginalCaster can become nullptr
- if (Unit* originalCaster = GetOriginalCaster())
- if (GameObject* go = GetHitGObj())
- if (go->GetGOInfo()->type == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING)
- originalCaster->CastSpell(originalCaster, SPELL_PLANT_CHARGES_CREDIT_ACHIEVEMENT, true);
- }
+ bool Load() override
+ {
+ // OriginalCaster is always available in Spell::prepare
+ return GetOriginalCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_seaforium_blast_SpellScript::AchievementCredit, EFFECT_1, SPELL_EFFECT_GAMEOBJECT_DAMAGE);
- }
- };
+ void AchievementCredit(SpellEffIndex /*effIndex*/)
+ {
+ // but in effect handling OriginalCaster can become nullptr
+ if (Unit* originalCaster = GetOriginalCaster())
+ if (GameObject* go = GetHitGObj())
+ if (go->GetGOInfo()->type == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING)
+ originalCaster->CastSpell(originalCaster, SPELL_PLANT_CHARGES_CREDIT_ACHIEVEMENT, true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_seaforium_blast_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_seaforium_blast::AchievementCredit, EFFECT_1, SPELL_EFFECT_GAMEOBJECT_DAMAGE);
+ }
};
enum SpectatorCheerTrigger
@@ -2971,67 +2448,45 @@ enum SpectatorCheerTrigger
uint8 const EmoteArray[3] = { EMOTE_ONE_SHOT_CHEER, EMOTE_ONE_SHOT_EXCLAMATION, EMOTE_ONE_SHOT_APPLAUD };
-class spell_gen_spectator_cheer_trigger : public SpellScriptLoader
+class spell_gen_spectator_cheer_trigger : public SpellScript
{
- public:
- spell_gen_spectator_cheer_trigger() : SpellScriptLoader("spell_gen_spectator_cheer_trigger") { }
-
- class spell_gen_spectator_cheer_trigger_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_spectator_cheer_trigger_SpellScript);
+ PrepareSpellScript(spell_gen_spectator_cheer_trigger);
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- GetCaster()->HandleEmoteCommand(EmoteArray[urand(0, 2)]);
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_spectator_cheer_trigger_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->HandleEmoteCommand(EmoteArray[urand(0, 2)]);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_spectator_cheer_trigger_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_spectator_cheer_trigger::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
-class spell_gen_spirit_healer_res : public SpellScriptLoader
+class spell_gen_spirit_healer_res : public SpellScript
{
- public:
- spell_gen_spirit_healer_res(): SpellScriptLoader("spell_gen_spirit_healer_res") { }
-
- class spell_gen_spirit_healer_res_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_spirit_healer_res_SpellScript);
-
- bool Load() override
- {
- return GetOriginalCaster() && GetOriginalCaster()->GetTypeId() == TYPEID_PLAYER;
- }
-
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- Player* originalCaster = GetOriginalCaster()->ToPlayer();
- if (Unit* target = GetHitUnit())
- {
- WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8);
- data << uint64(target->GetGUID());
- originalCaster->SendDirectMessage(&data);
- }
- }
+ PrepareSpellScript(spell_gen_spirit_healer_res);
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_spirit_healer_res_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ bool Load() override
+ {
+ return GetOriginalCaster() && GetOriginalCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- SpellScript* GetSpellScript() const override
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ Player* originalCaster = GetOriginalCaster()->ToPlayer();
+ if (Unit* target = GetHitUnit())
{
- return new spell_gen_spirit_healer_res_SpellScript();
+ WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8);
+ data << uint64(target->GetGUID());
+ originalCaster->SendDirectMessage(&data);
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_spirit_healer_res::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum SummonElemental
@@ -3096,72 +2551,50 @@ enum TournamentMountsSpells
SPELL_LANCE_EQUIPPED = 62853
};
-class spell_gen_summon_tournament_mount : public SpellScriptLoader
+class spell_gen_summon_tournament_mount : public SpellScript
{
- public:
- spell_gen_summon_tournament_mount() : SpellScriptLoader("spell_gen_summon_tournament_mount") { }
-
- class spell_gen_summon_tournament_mount_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_summon_tournament_mount_SpellScript);
+ PrepareSpellScript(spell_gen_summon_tournament_mount);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_LANCE_EQUIPPED });
- }
-
- SpellCastResult CheckIfLanceEquiped()
- {
- if (GetCaster()->IsInDisallowedMountForm())
- GetCaster()->RemoveAurasByType(SPELL_AURA_MOD_SHAPESHIFT);
-
- if (!GetCaster()->HasAura(SPELL_LANCE_EQUIPPED))
- {
- SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_MUST_HAVE_LANCE_EQUIPPED);
- return SPELL_FAILED_CUSTOM_ERROR;
- }
-
- return SPELL_CAST_OK;
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_LANCE_EQUIPPED });
+ }
- void Register() override
- {
- OnCheckCast += SpellCheckCastFn(spell_gen_summon_tournament_mount_SpellScript::CheckIfLanceEquiped);
- }
- };
+ SpellCastResult CheckIfLanceEquiped()
+ {
+ if (GetCaster()->IsInDisallowedMountForm())
+ GetCaster()->RemoveAurasByType(SPELL_AURA_MOD_SHAPESHIFT);
- SpellScript* GetSpellScript() const override
+ if (!GetCaster()->HasAura(SPELL_LANCE_EQUIPPED))
{
- return new spell_gen_summon_tournament_mount_SpellScript();
+ SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_MUST_HAVE_LANCE_EQUIPPED);
+ return SPELL_FAILED_CUSTOM_ERROR;
}
+
+ return SPELL_CAST_OK;
+ }
+
+ void Register() override
+ {
+ OnCheckCast += SpellCheckCastFn(spell_gen_summon_tournament_mount::CheckIfLanceEquiped);
+ }
};
// 41213, 43416, 69222, 73076 - Throw Shield
-class spell_gen_throw_shield : public SpellScriptLoader
+class spell_gen_throw_shield : public SpellScript
{
- public:
- spell_gen_throw_shield() : SpellScriptLoader("spell_gen_throw_shield") { }
-
- class spell_gen_throw_shield_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_throw_shield_SpellScript);
-
- void HandleScriptEffect(SpellEffIndex effIndex)
- {
- PreventHitDefaultEffect(effIndex);
- GetCaster()->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true);
- }
+ PrepareSpellScript(spell_gen_throw_shield);
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_throw_shield_SpellScript::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ void HandleScriptEffect(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ GetCaster()->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_throw_shield_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_throw_shield::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
enum MountedDuelSpells
@@ -3170,84 +2603,62 @@ enum MountedDuelSpells
SPELL_MOUNTED_DUEL = 62875
};
-class spell_gen_tournament_duel : public SpellScriptLoader
+class spell_gen_tournament_duel : public SpellScript
{
- public:
- spell_gen_tournament_duel() : SpellScriptLoader("spell_gen_tournament_duel") { }
+ PrepareSpellScript(spell_gen_tournament_duel);
- class spell_gen_tournament_duel_SpellScript : public SpellScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareSpellScript(spell_gen_tournament_duel_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_ON_TOURNAMENT_MOUNT,
- SPELL_MOUNTED_DUEL
- });
- }
+ SPELL_ON_TOURNAMENT_MOUNT,
+ SPELL_MOUNTED_DUEL
+ });
+ }
- void HandleScriptEffect(SpellEffIndex /*effIndex*/)
+ void HandleScriptEffect(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* rider = GetCaster()->GetCharmer())
+ {
+ if (Player* playerTarget = GetHitPlayer())
{
- if (Unit* rider = GetCaster()->GetCharmer())
- {
- if (Player* playerTarget = GetHitPlayer())
- {
- if (playerTarget->HasAura(SPELL_ON_TOURNAMENT_MOUNT) && playerTarget->GetVehicleBase())
- rider->CastSpell(playerTarget, SPELL_MOUNTED_DUEL, true);
- }
- else if (Unit* unitTarget = GetHitUnit())
- {
- if (unitTarget->GetCharmer() && unitTarget->GetCharmer()->GetTypeId() == TYPEID_PLAYER && unitTarget->GetCharmer()->HasAura(SPELL_ON_TOURNAMENT_MOUNT))
- rider->CastSpell(unitTarget->GetCharmer(), SPELL_MOUNTED_DUEL, true);
- }
- }
+ if (playerTarget->HasAura(SPELL_ON_TOURNAMENT_MOUNT) && playerTarget->GetVehicleBase())
+ rider->CastSpell(playerTarget, SPELL_MOUNTED_DUEL, true);
}
-
- void Register() override
+ else if (Unit* unitTarget = GetHitUnit())
{
- OnEffectHitTarget += SpellEffectFn(spell_gen_tournament_duel_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ if (unitTarget->GetCharmer() && unitTarget->GetCharmer()->GetTypeId() == TYPEID_PLAYER && unitTarget->GetCharmer()->HasAura(SPELL_ON_TOURNAMENT_MOUNT))
+ rider->CastSpell(unitTarget->GetCharmer(), SPELL_MOUNTED_DUEL, true);
}
- };
-
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_tournament_duel_SpellScript();
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_tournament_duel::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
-class spell_gen_tournament_pennant : public SpellScriptLoader
+class spell_gen_tournament_pennant : public AuraScript
{
- public:
- spell_gen_tournament_pennant() : SpellScriptLoader("spell_gen_tournament_pennant") { }
-
- class spell_gen_tournament_pennant_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_tournament_pennant_AuraScript);
-
- bool Load() override
- {
- return GetCaster() && GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
+ PrepareAuraScript(spell_gen_tournament_pennant);
- void HandleApplyEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- if (Unit* caster = GetCaster())
- if (!caster->GetVehicleBase())
- caster->RemoveAurasDueToSpell(GetId());
- }
+ bool Load() override
+ {
+ return GetCaster() && GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- void Register() override
- {
- OnEffectApply += AuraEffectApplyFn(spell_gen_tournament_pennant_AuraScript::HandleApplyEffect, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
- }
- };
+ void HandleApplyEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* caster = GetCaster())
+ if (!caster->GetVehicleBase())
+ caster->RemoveAurasDueToSpell(GetId());
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_tournament_pennant_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectApply += AuraEffectApplyFn(spell_gen_tournament_pennant::HandleApplyEffect, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
+ }
};
enum PvPTrinketTriggeredSpells
@@ -3294,7 +2705,7 @@ class spell_pvp_trinket_wotf_shared_cd : public SpellScriptLoader
*/
// Spell flags need further research, until then just cast not triggered
- GetCaster()->CastSpell((Unit*)nullptr, Triggered, false);
+ GetCaster()->CastSpell(nullptr, Triggered, false);
}
void Register() override
@@ -3314,49 +2725,38 @@ enum FriendOrFowl
SPELL_TURKEY_VENGEANCE = 25285
};
-class spell_gen_turkey_marker : public SpellScriptLoader
+class spell_gen_turkey_marker : public AuraScript
{
- public:
- spell_gen_turkey_marker() : SpellScriptLoader("spell_gen_turkey_marker") { }
-
- class spell_gen_turkey_marker_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_turkey_marker_AuraScript);
-
- void OnApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
- {
- // store stack apply times, so we can pop them while they expire
- _applyTimes.push_back(GameTime::GetGameTimeMS());
- Unit* target = GetTarget();
+ PrepareAuraScript(spell_gen_turkey_marker);
- // on stack 15 cast the achievement crediting spell
- if (GetStackAmount() >= 15)
- target->CastSpell(target, SPELL_TURKEY_VENGEANCE, true, nullptr, aurEff, GetCasterGUID());
- }
+ void OnApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
+ {
+ // store stack apply times, so we can pop them while they expire
+ _applyTimes.push_back(GameTime::GetGameTimeMS());
+ Unit* target = GetTarget();
- void OnPeriodic(AuraEffect const* /*aurEff*/)
- {
- if (_applyTimes.empty())
- return;
+ // on stack 15 cast the achievement crediting spell
+ if (GetStackAmount() >= 15)
+ target->CastSpell(target, SPELL_TURKEY_VENGEANCE, true, nullptr, aurEff, GetCasterGUID());
+ }
- // pop stack if it expired for us
- if (_applyTimes.front() + GetMaxDuration() < GameTime::GetGameTimeMS())
- ModStackAmount(-1, AURA_REMOVE_BY_EXPIRE);
- }
+ void OnPeriodic(AuraEffect const* /*aurEff*/)
+ {
+ if (_applyTimes.empty())
+ return;
- void Register() override
- {
- AfterEffectApply += AuraEffectApplyFn(spell_gen_turkey_marker_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_gen_turkey_marker_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
- }
+ // pop stack if it expired for us
+ if (_applyTimes.front() + GetMaxDuration() < GameTime::GetGameTimeMS())
+ ModStackAmount(-1, AURA_REMOVE_BY_EXPIRE);
+ }
- std::list<uint32> _applyTimes;
- };
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_gen_turkey_marker::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_gen_turkey_marker::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_turkey_marker_AuraScript();
- }
+ std::list<uint32> _applyTimes;
};
enum FoamSword
@@ -3368,41 +2768,30 @@ enum FoamSword
ITEM_FOAM_SWORD_YELLOW = 45179
};
-class spell_gen_upper_deck_create_foam_sword : public SpellScriptLoader
+class spell_gen_upper_deck_create_foam_sword : public SpellScript
{
- public:
- spell_gen_upper_deck_create_foam_sword() : SpellScriptLoader("spell_gen_upper_deck_create_foam_sword") { }
+ PrepareSpellScript(spell_gen_upper_deck_create_foam_sword);
- class spell_gen_upper_deck_create_foam_sword_SpellScript : public SpellScript
+ void HandleScript(SpellEffIndex effIndex)
+ {
+ if (Player* player = GetHitPlayer())
{
- PrepareSpellScript(spell_gen_upper_deck_create_foam_sword_SpellScript);
-
- void HandleScript(SpellEffIndex effIndex)
- {
- if (Player* player = GetHitPlayer())
- {
- static uint32 const itemId[5] = { ITEM_FOAM_SWORD_GREEN, ITEM_FOAM_SWORD_PINK, ITEM_FOAM_SWORD_BLUE, ITEM_FOAM_SWORD_RED, ITEM_FOAM_SWORD_YELLOW };
- // player can only have one of these items
- for (uint8 i = 0; i < 5; ++i)
- {
- if (player->HasItemCount(itemId[i], 1, true))
- return;
- }
-
- CreateItem(effIndex, itemId[urand(0, 4)]);
- }
- }
-
- void Register() override
+ static uint32 const itemId[5] = { ITEM_FOAM_SWORD_GREEN, ITEM_FOAM_SWORD_PINK, ITEM_FOAM_SWORD_BLUE, ITEM_FOAM_SWORD_RED, ITEM_FOAM_SWORD_YELLOW };
+ // player can only have one of these items
+ for (uint8 i = 0; i < 5; ++i)
{
- OnEffectHitTarget += SpellEffectFn(spell_gen_upper_deck_create_foam_sword_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ if (player->HasItemCount(itemId[i], 1, true))
+ return;
}
- };
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_upper_deck_create_foam_sword_SpellScript();
+ CreateItem(effIndex, itemId[urand(0, 4)]);
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_upper_deck_create_foam_sword::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
enum VampiricTouch
@@ -3412,42 +2801,31 @@ enum VampiricTouch
// 52723 - Vampiric Touch
// 60501 - Vampiric Touch
-class spell_gen_vampiric_touch : public SpellScriptLoader
+class spell_gen_vampiric_touch : public AuraScript
{
- public:
- spell_gen_vampiric_touch() : SpellScriptLoader("spell_gen_vampiric_touch") { }
+ PrepareAuraScript(spell_gen_vampiric_touch);
- class spell_gen_vampiric_touch_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_vampiric_touch_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_VAMPIRIC_TOUCH_HEAL });
- }
-
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
- DamageInfo* damageInfo = eventInfo.GetDamageInfo();
- if (!damageInfo || !damageInfo->GetDamage())
- return;
-
- Unit* caster = eventInfo.GetActor();
- int32 bp = damageInfo->GetDamage() / 2;
- caster->CastCustomSpell(SPELL_VAMPIRIC_TOUCH_HEAL, SPELLVALUE_BASE_POINT0, bp, caster, true, nullptr, aurEff);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_VAMPIRIC_TOUCH_HEAL });
+ }
- void Register() override
- {
- OnEffectProc += AuraEffectProcFn(spell_gen_vampiric_touch_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
- }
- };
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+ DamageInfo* damageInfo = eventInfo.GetDamageInfo();
+ if (!damageInfo || !damageInfo->GetDamage())
+ return;
+
+ Unit* caster = eventInfo.GetActor();
+ int32 bp = damageInfo->GetDamage() / 2;
+ caster->CastCustomSpell(SPELL_VAMPIRIC_TOUCH_HEAL, SPELLVALUE_BASE_POINT0, bp, caster, true, nullptr, aurEff);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_vampiric_touch_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_gen_vampiric_touch::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
+ }
};
enum VehicleScaling
@@ -3455,58 +2833,47 @@ enum VehicleScaling
SPELL_GEAR_SCALING = 66668
};
-class spell_gen_vehicle_scaling : public SpellScriptLoader
+class spell_gen_vehicle_scaling : public AuraScript
{
- public:
- spell_gen_vehicle_scaling() : SpellScriptLoader("spell_gen_vehicle_scaling") { }
-
- class spell_gen_vehicle_scaling_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_vehicle_scaling_AuraScript);
+ PrepareAuraScript(spell_gen_vehicle_scaling);
- bool Load() override
- {
- return GetCaster() && GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
-
- void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
- {
- Unit* caster = GetCaster();
- float factor;
- uint16 baseItemLevel;
+ bool Load() override
+ {
+ return GetCaster() && GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- /// @todo Reserach coeffs for different vehicles
- switch (GetId())
- {
- case SPELL_GEAR_SCALING:
- factor = 1.0f;
- baseItemLevel = 205;
- break;
- default:
- factor = 1.0f;
- baseItemLevel = 170;
- break;
- }
+ void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
+ {
+ Unit* caster = GetCaster();
+ float factor;
+ uint16 baseItemLevel;
- float avgILvl = caster->ToPlayer()->GetAverageItemLevel();
- if (avgILvl < baseItemLevel)
- return; /// @todo Research possibility of scaling down
+ /// @todo Reserach coeffs for different vehicles
+ switch (GetId())
+ {
+ case SPELL_GEAR_SCALING:
+ factor = 1.0f;
+ baseItemLevel = 205;
+ break;
+ default:
+ factor = 1.0f;
+ baseItemLevel = 170;
+ break;
+ }
- amount = uint16((avgILvl - baseItemLevel) * factor);
- }
+ float avgILvl = caster->ToPlayer()->GetAverageItemLevel();
+ if (avgILvl < baseItemLevel)
+ return; /// @todo Research possibility of scaling down
- void Register() override
- {
- DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_vehicle_scaling_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_HEALING_PCT);
- DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_vehicle_scaling_AuraScript::CalculateAmount, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
- DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_vehicle_scaling_AuraScript::CalculateAmount, EFFECT_2, SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT);
- }
- };
+ amount = uint16((avgILvl - baseItemLevel) * factor);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_vehicle_scaling_AuraScript();
- }
+ void Register() override
+ {
+ DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_vehicle_scaling::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_HEALING_PCT);
+ DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_vehicle_scaling::CalculateAmount, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
+ DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_vehicle_scaling::CalculateAmount, EFFECT_2, SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT);
+ }
};
enum VendorBarkTrigger
@@ -3515,61 +2882,38 @@ enum VendorBarkTrigger
SAY_AMPHITHEATER_VENDOR = 0
};
-class spell_gen_vendor_bark_trigger : public SpellScriptLoader
+class spell_gen_vendor_bark_trigger : public SpellScript
{
- public:
- spell_gen_vendor_bark_trigger() : SpellScriptLoader("spell_gen_vendor_bark_trigger") { }
-
- class spell_gen_vendor_bark_trigger_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_vendor_bark_trigger_SpellScript);
+ PrepareSpellScript(spell_gen_vendor_bark_trigger);
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- if (Creature* vendor = GetCaster()->ToCreature())
- if (vendor->GetEntry() == NPC_AMPHITHEATER_VENDOR)
- vendor->AI()->Talk(SAY_AMPHITHEATER_VENDOR);
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_vendor_bark_trigger_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
-
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_vendor_bark_trigger_SpellScript();
- }
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ if (Creature* vendor = GetCaster()->ToCreature())
+ if (vendor->GetEntry() == NPC_AMPHITHEATER_VENDOR)
+ vendor->AI()->Talk(SAY_AMPHITHEATER_VENDOR);
+ }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_vendor_bark_trigger::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
-class spell_gen_wg_water : public SpellScriptLoader
+class spell_gen_wg_water : public SpellScript
{
- public:
- spell_gen_wg_water() : SpellScriptLoader("spell_gen_wg_water") { }
-
- class spell_gen_wg_water_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_wg_water_SpellScript);
-
- SpellCastResult CheckCast()
- {
- if (!GetSpellInfo()->CheckTargetCreatureType(GetCaster()))
- return SPELL_FAILED_DONT_REPORT;
- return SPELL_CAST_OK;
- }
+ PrepareSpellScript(spell_gen_wg_water);
- void Register() override
- {
- OnCheckCast += SpellCheckCastFn(spell_gen_wg_water_SpellScript::CheckCast);
- }
- };
+ SpellCastResult CheckCast()
+ {
+ if (!GetSpellInfo()->CheckTargetCreatureType(GetCaster()))
+ return SPELL_FAILED_DONT_REPORT;
+ return SPELL_CAST_OK;
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_wg_water_SpellScript();
- }
+ void Register() override
+ {
+ OnCheckCast += SpellCheckCastFn(spell_gen_wg_water::CheckCast);
+ }
};
enum WhisperGulchYoggSaronWhisper
@@ -3577,100 +2921,67 @@ enum WhisperGulchYoggSaronWhisper
SPELL_YOGG_SARON_WHISPER_DUMMY = 29072
};
-class spell_gen_whisper_gulch_yogg_saron_whisper : public SpellScriptLoader
+class spell_gen_whisper_gulch_yogg_saron_whisper : public AuraScript
{
- public:
- spell_gen_whisper_gulch_yogg_saron_whisper() : SpellScriptLoader("spell_gen_whisper_gulch_yogg_saron_whisper") { }
-
- class spell_gen_whisper_gulch_yogg_saron_whisper_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_whisper_gulch_yogg_saron_whisper_AuraScript);
+ PrepareAuraScript(spell_gen_whisper_gulch_yogg_saron_whisper);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_YOGG_SARON_WHISPER_DUMMY });
- }
-
- void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
- {
- PreventDefaultAction();
- GetTarget()->CastSpell((Unit*)nullptr, SPELL_YOGG_SARON_WHISPER_DUMMY, true);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_YOGG_SARON_WHISPER_DUMMY });
+ }
- void Register() override
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_gen_whisper_gulch_yogg_saron_whisper_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
- }
- };
+ void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
+ {
+ PreventDefaultAction();
+ GetTarget()->CastSpell(nullptr, SPELL_YOGG_SARON_WHISPER_DUMMY, true);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_whisper_gulch_yogg_saron_whisper_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_gen_whisper_gulch_yogg_saron_whisper::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
};
-class spell_gen_eject_all_passengers : public SpellScriptLoader
+class spell_gen_eject_all_passengers : public SpellScript
{
- public:
- spell_gen_eject_all_passengers() : SpellScriptLoader("spell_gen_eject_all_passengers") { }
-
- class spell_gen_eject_all_passengers_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_eject_all_passengers_SpellScript);
-
- void RemoveVehicleAuras()
- {
- if (Vehicle* vehicle = GetHitUnit()->GetVehicleKit())
- vehicle->RemoveAllPassengers();
- }
+ PrepareSpellScript(spell_gen_eject_all_passengers);
- void Register() override
- {
- AfterHit += SpellHitFn(spell_gen_eject_all_passengers_SpellScript::RemoveVehicleAuras);
- }
- };
+ void RemoveVehicleAuras()
+ {
+ if (Vehicle* vehicle = GetHitUnit()->GetVehicleKit())
+ vehicle->RemoveAllPassengers();
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_eject_all_passengers_SpellScript();
- }
+ void Register() override
+ {
+ AfterHit += SpellHitFn(spell_gen_eject_all_passengers::RemoveVehicleAuras);
+ }
};
-class spell_gen_eject_passenger : public SpellScriptLoader
+class spell_gen_eject_passenger : public SpellScript
{
- public:
- spell_gen_eject_passenger() : SpellScriptLoader("spell_gen_eject_passenger") { }
-
- class spell_gen_eject_passenger_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gen_eject_passenger_SpellScript);
-
- bool Validate(SpellInfo const* spellInfo) override
- {
- if (spellInfo->Effects[EFFECT_0].CalcValue() < 1)
- return false;
- return true;
- }
-
- void EjectPassenger(SpellEffIndex /*effIndex*/)
- {
- if (Vehicle* vehicle = GetHitUnit()->GetVehicleKit())
- {
- if (Unit* passenger = vehicle->GetPassenger(GetEffectValue() - 1))
- passenger->ExitVehicle();
- }
- }
+ PrepareSpellScript(spell_gen_eject_passenger);
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_eject_passenger_SpellScript::EjectPassenger, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ bool Validate(SpellInfo const* spellInfo) override
+ {
+ if (spellInfo->Effects[EFFECT_0].CalcValue() < 1)
+ return false;
+ return true;
+ }
- SpellScript* GetSpellScript() const override
+ void EjectPassenger(SpellEffIndex /*effIndex*/)
+ {
+ if (Vehicle* vehicle = GetHitUnit()->GetVehicleKit())
{
- return new spell_gen_eject_passenger_SpellScript();
+ if (Unit* passenger = vehicle->GetPassenger(GetEffectValue() - 1))
+ passenger->ExitVehicle();
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_eject_passenger::EjectPassenger, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
enum GMFreeze
@@ -3678,100 +2989,78 @@ enum GMFreeze
SPELL_GM_FREEZE = 9454
};
-class spell_gen_gm_freeze : public SpellScriptLoader
+class spell_gen_gm_freeze : public AuraScript
{
- public:
- spell_gen_gm_freeze() : SpellScriptLoader("spell_gen_gm_freeze") { }
-
- class spell_gen_gm_freeze_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_gm_freeze_AuraScript);
+ PrepareAuraScript(spell_gen_gm_freeze);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_GM_FREEZE });
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_GM_FREEZE });
+ }
- void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- // Do what was done before to the target in HandleFreezeCommand
- if (Player* player = GetTarget()->ToPlayer())
- {
- // stop combat + make player unattackable + duel stop + stop some spells
- player->SetFaction(FACTION_FRIENDLY);
- player->CombatStop();
- if (player->IsNonMeleeSpellCast(true))
- player->InterruptNonMeleeSpells(true);
- player->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
-
- // 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->IsAlive())
- player->RemovePet(pet, PET_SAVE_NOT_IN_SLOT);
- }
- }
- }
- }
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ // Do what was done before to the target in HandleFreezeCommand
+ if (Player* player = GetTarget()->ToPlayer())
+ {
+ // stop combat + make player unattackable + duel stop + stop some spells
+ player->SetFaction(FACTION_FRIENDLY);
+ player->CombatStop();
+ if (player->IsNonMeleeSpellCast(true))
+ player->InterruptNonMeleeSpells(true);
+ player->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ // if player class = hunter || warlock remove pet if alive
+ if ((player->getClass() == CLASS_HUNTER) || (player->getClass() == CLASS_WARLOCK))
{
- // Do what was done before to the target in HandleUnfreezeCommand
- if (Player* player = GetTarget()->ToPlayer())
+ if (Pet* pet = player->GetPet())
{
- // Reset player faction + allow combat + allow duels
- player->setFactionForRace(player->getRace());
- player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- // save player
- player->SaveToDB();
+ pet->SavePetToDB(PET_SAVE_AS_CURRENT);
+ // not let dismiss dead pet
+ if (pet->IsAlive())
+ player->RemovePet(pet, PET_SAVE_NOT_IN_SLOT);
}
}
+ }
+ }
- void Register() override
- {
- OnEffectApply += AuraEffectApplyFn(spell_gen_gm_freeze_AuraScript::OnApply, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
- OnEffectRemove += AuraEffectRemoveFn(spell_gen_gm_freeze_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
- }
- };
-
- AuraScript* GetAuraScript() const override
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ // Do what was done before to the target in HandleUnfreezeCommand
+ if (Player* player = GetTarget()->ToPlayer())
{
- return new spell_gen_gm_freeze_AuraScript();
+ // Reset player faction + allow combat + allow duels
+ player->setFactionForRace(player->getRace());
+ player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ // save player
+ player->SaveToDB();
}
+ }
+
+ void Register() override
+ {
+ OnEffectApply += AuraEffectApplyFn(spell_gen_gm_freeze::OnApply, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
+ OnEffectRemove += AuraEffectRemoveFn(spell_gen_gm_freeze::OnRemove, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
+ }
};
-class spell_gen_stand : public SpellScriptLoader
+class spell_gen_stand : public SpellScript
{
-public:
- spell_gen_stand() : SpellScriptLoader("spell_gen_stand") { }
+ PrepareSpellScript(spell_gen_stand);
- class spell_gen_stand_SpellScript : public SpellScript
+ void HandleScript(SpellEffIndex /*eff*/)
{
- PrepareSpellScript(spell_gen_stand_SpellScript);
-
- void HandleScript(SpellEffIndex /*eff*/)
- {
- Creature* target = GetHitCreature();
- if (!target)
- return;
+ Creature* target = GetHitCreature();
+ if (!target)
+ return;
- target->SetStandState(UNIT_STAND_STATE_STAND);
- target->HandleEmoteCommand(EMOTE_STATE_NONE);
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_stand_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ target->SetStandState(UNIT_STAND_STATE_STAND);
+ target->HandleEmoteCommand(EMOTE_STATE_NONE);
+ }
- SpellScript* GetSpellScript() const override
+ void Register() override
{
- return new spell_gen_stand_SpellScript();
+ OnEffectHitTarget += SpellEffectFn(spell_gen_stand::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
@@ -3863,214 +3152,203 @@ enum RequiredMixologySpells
SPELL_ELIXIR_OF_MINOR_DEFENSE = 673
};
-class spell_gen_mixology_bonus : public SpellScriptLoader
+class spell_gen_mixology_bonus : public AuraScript
{
-public:
- spell_gen_mixology_bonus() : SpellScriptLoader("spell_gen_mixology_bonus") { }
+ PrepareAuraScript(spell_gen_mixology_bonus);
- class spell_gen_mixology_bonus_AuraScript : public AuraScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
{
- PrepareAuraScript(spell_gen_mixology_bonus_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_MIXOLOGY });
- }
+ return ValidateSpellInfo({ SPELL_MIXOLOGY });
+ }
- bool Load() override
- {
- return GetCaster() && GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
+ bool Load() override
+ {
+ return GetCaster() && GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- void SetBonusValueForEffect(SpellEffIndex effIndex, int32 value, AuraEffect const* aurEff)
- {
- if (aurEff->GetEffIndex() == uint32(effIndex))
- bonus = value;
- }
+ void SetBonusValueForEffect(SpellEffIndex effIndex, int32 value, AuraEffect const* aurEff)
+ {
+ if (aurEff->GetEffIndex() == uint32(effIndex))
+ bonus = value;
+ }
- void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/)
- {
- if (GetCaster()->HasAura(SPELL_MIXOLOGY) && GetCaster()->HasSpell(GetSpellInfo()->Effects[EFFECT_0].TriggerSpell))
- {
- switch (GetId())
- {
- case SPELL_WEAK_TROLLS_BLOOD_ELIXIR:
- case SPELL_MAGEBLOOD_ELIXIR:
- bonus = amount;
- break;
- case SPELL_ELIXIR_OF_FROST_POWER:
- case SPELL_LESSER_FLASK_OF_TOUGHNESS:
- case SPELL_LESSER_FLASK_OF_RESISTANCE:
- bonus = CalculatePct(amount, 80);
- break;
- case SPELL_ELIXIR_OF_MINOR_DEFENSE:
- case SPELL_ELIXIR_OF_LIONS_STRENGTH:
- case SPELL_ELIXIR_OF_MINOR_AGILITY:
- case SPELL_MAJOR_TROLLS_BLLOOD_ELIXIR:
- case SPELL_ELIXIR_OF_SHADOW_POWER:
- case SPELL_ELIXIR_OF_BRUTE_FORCE:
- case SPELL_MIGHTY_TROLLS_BLOOD_ELIXIR:
- case SPELL_ELIXIR_OF_GREATER_FIREPOWER:
- case SPELL_ONSLAUGHT_ELIXIR:
- case SPELL_EARTHEN_ELIXIR:
- case SPELL_ELIXIR_OF_MAJOR_AGILITY:
- case SPELL_FLASK_OF_THE_TITANS:
- case SPELL_FLASK_OF_RELENTLESS_ASSAULT:
- case SPELL_FLASK_OF_STONEBLOOD:
- case SPELL_ELIXIR_OF_MINOR_ACCURACY:
- bonus = CalculatePct(amount, 50);
- break;
- case SPELL_ELIXIR_OF_PROTECTION:
- bonus = 280;
- break;
- case SPELL_ELIXIR_OF_MAJOR_DEFENSE:
- bonus = 200;
- break;
- case SPELL_ELIXIR_OF_GREATER_DEFENSE:
- case SPELL_ELIXIR_OF_SUPERIOR_DEFENSE:
- bonus = 140;
- break;
- case SPELL_ELIXIR_OF_FORTITUDE:
- bonus = 100;
- break;
- case SPELL_FLASK_OF_ENDLESS_RAGE:
- bonus = 82;
- break;
- case SPELL_ELIXIR_OF_DEFENSE:
- bonus = 70;
- break;
- case SPELL_ELIXIR_OF_DEMONSLAYING:
- bonus = 50;
- break;
- case SPELL_FLASK_OF_THE_FROST_WYRM:
- bonus = 47;
- break;
- case SPELL_WRATH_ELIXIR:
- bonus = 32;
- break;
- case SPELL_ELIXIR_OF_MAJOR_FROST_POWER:
- case SPELL_ELIXIR_OF_MAJOR_FIREPOWER:
- case SPELL_ELIXIR_OF_MAJOR_SHADOW_POWER:
- bonus = 29;
- break;
- case SPELL_ELIXIR_OF_MIGHTY_TOUGHTS:
- bonus = 27;
- break;
- case SPELL_FLASK_OF_SUPREME_POWER:
- case SPELL_FLASK_OF_BLINDING_LIGHT:
- case SPELL_FLASK_OF_PURE_DEATH:
- case SPELL_SHADOWPOWER_ELIXIR:
- bonus = 23;
- break;
- case SPELL_ELIXIR_OF_MIGHTY_AGILITY:
- case SPELL_FLASK_OF_DISTILLED_WISDOM:
- case SPELL_ELIXIR_OF_SPIRIT:
- case SPELL_ELIXIR_OF_MIGHTY_STRENGTH:
- case SPELL_FLASK_OF_PURE_MOJO:
- case SPELL_ELIXIR_OF_ACCURACY:
- case SPELL_ELIXIR_OF_DEADLY_STRIKES:
- case SPELL_ELIXIR_OF_MIGHTY_DEFENSE:
- case SPELL_ELIXIR_OF_EXPERTISE:
- case SPELL_ELIXIR_OF_ARMOR_PIERCING:
- case SPELL_ELIXIR_OF_LIGHTNING_SPEED:
- bonus = 20;
- break;
- case SPELL_FLASK_OF_CHROMATIC_RESISTANCE:
- bonus = 17;
- break;
- case SPELL_ELIXIR_OF_MINOR_FORTITUDE:
- case SPELL_ELIXIR_OF_MAJOR_STRENGTH:
- bonus = 15;
- break;
- case SPELL_FLASK_OF_MIGHTY_RESTORATION:
- bonus = 13;
- break;
- case SPELL_ARCANE_ELIXIR:
- bonus = 12;
- break;
- case SPELL_ELIXIR_OF_GREATER_AGILITY:
- case SPELL_ELIXIR_OF_GIANTS:
- bonus = 11;
- break;
- case SPELL_ELIXIR_OF_AGILITY:
- case SPELL_ELIXIR_OF_GREATER_INTELLECT:
- case SPELL_ELIXIR_OF_SAGES:
- case SPELL_ELIXIR_OF_IRONSKIN:
- case SPELL_ELIXIR_OF_MIGHTY_MAGEBLOOD:
- bonus = 10;
- break;
- case SPELL_ELIXIR_OF_HEALING_POWER:
- bonus = 9;
- break;
- case SPELL_ELIXIR_OF_DRAENIC_WISDOM:
- case SPELL_GURUS_ELIXIR:
- bonus = 8;
- break;
- case SPELL_ELIXIR_OF_FIREPOWER:
- case SPELL_ELIXIR_OF_MAJOR_MAGEBLOOD:
- case SPELL_ELIXIR_OF_MASTERY:
- bonus = 6;
- break;
- case SPELL_ELIXIR_OF_LESSER_AGILITY:
- case SPELL_ELIXIR_OF_OGRES_STRENGTH:
- case SPELL_ELIXIR_OF_WISDOM:
- case SPELL_ELIXIR_OF_THE_MONGOOSE:
- bonus = 5;
- break;
- case SPELL_STRONG_TROLLS_BLOOD_ELIXIR:
- case SPELL_FLASK_OF_CHROMATIC_WONDER:
- bonus = 4;
- break;
- case SPELL_ELIXIR_OF_EMPOWERMENT:
- bonus = -10;
- break;
- case SPELL_ADEPTS_ELIXIR:
- SetBonusValueForEffect(EFFECT_0, 13, aurEff);
- SetBonusValueForEffect(EFFECT_1, 13, aurEff);
- SetBonusValueForEffect(EFFECT_2, 8, aurEff);
- break;
- case SPELL_ELIXIR_OF_MIGHTY_FORTITUDE:
- SetBonusValueForEffect(EFFECT_0, 160, aurEff);
- break;
- case SPELL_ELIXIR_OF_MAJOR_FORTITUDE:
- SetBonusValueForEffect(EFFECT_0, 116, aurEff);
- SetBonusValueForEffect(EFFECT_1, 6, aurEff);
- break;
- case SPELL_FEL_STRENGTH_ELIXIR:
- SetBonusValueForEffect(EFFECT_0, 40, aurEff);
- SetBonusValueForEffect(EFFECT_1, 40, aurEff);
- break;
- case SPELL_FLASK_OF_FORTIFICATION:
- SetBonusValueForEffect(EFFECT_0, 210, aurEff);
- SetBonusValueForEffect(EFFECT_1, 5, aurEff);
- break;
- case SPELL_GREATER_ARCANE_ELIXIR:
- SetBonusValueForEffect(EFFECT_0, 19, aurEff);
- SetBonusValueForEffect(EFFECT_1, 19, aurEff);
- SetBonusValueForEffect(EFFECT_2, 5, aurEff);
- break;
- case SPELL_ELIXIR_OF_GIANTH_GROWTH:
- SetBonusValueForEffect(EFFECT_0, 5, aurEff);
- break;
- default:
- TC_LOG_ERROR("spells", "SpellId %u couldn't be processed in spell_gen_mixology_bonus", GetId());
- break;
- }
- amount += bonus;
- }
+ void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/)
+ {
+ if (GetCaster()->HasAura(SPELL_MIXOLOGY) && GetCaster()->HasSpell(GetSpellInfo()->Effects[EFFECT_0].TriggerSpell))
+ {
+ switch (GetId())
+ {
+ case SPELL_WEAK_TROLLS_BLOOD_ELIXIR:
+ case SPELL_MAGEBLOOD_ELIXIR:
+ bonus = amount;
+ break;
+ case SPELL_ELIXIR_OF_FROST_POWER:
+ case SPELL_LESSER_FLASK_OF_TOUGHNESS:
+ case SPELL_LESSER_FLASK_OF_RESISTANCE:
+ bonus = CalculatePct(amount, 80);
+ break;
+ case SPELL_ELIXIR_OF_MINOR_DEFENSE:
+ case SPELL_ELIXIR_OF_LIONS_STRENGTH:
+ case SPELL_ELIXIR_OF_MINOR_AGILITY:
+ case SPELL_MAJOR_TROLLS_BLLOOD_ELIXIR:
+ case SPELL_ELIXIR_OF_SHADOW_POWER:
+ case SPELL_ELIXIR_OF_BRUTE_FORCE:
+ case SPELL_MIGHTY_TROLLS_BLOOD_ELIXIR:
+ case SPELL_ELIXIR_OF_GREATER_FIREPOWER:
+ case SPELL_ONSLAUGHT_ELIXIR:
+ case SPELL_EARTHEN_ELIXIR:
+ case SPELL_ELIXIR_OF_MAJOR_AGILITY:
+ case SPELL_FLASK_OF_THE_TITANS:
+ case SPELL_FLASK_OF_RELENTLESS_ASSAULT:
+ case SPELL_FLASK_OF_STONEBLOOD:
+ case SPELL_ELIXIR_OF_MINOR_ACCURACY:
+ bonus = CalculatePct(amount, 50);
+ break;
+ case SPELL_ELIXIR_OF_PROTECTION:
+ bonus = 280;
+ break;
+ case SPELL_ELIXIR_OF_MAJOR_DEFENSE:
+ bonus = 200;
+ break;
+ case SPELL_ELIXIR_OF_GREATER_DEFENSE:
+ case SPELL_ELIXIR_OF_SUPERIOR_DEFENSE:
+ bonus = 140;
+ break;
+ case SPELL_ELIXIR_OF_FORTITUDE:
+ bonus = 100;
+ break;
+ case SPELL_FLASK_OF_ENDLESS_RAGE:
+ bonus = 82;
+ break;
+ case SPELL_ELIXIR_OF_DEFENSE:
+ bonus = 70;
+ break;
+ case SPELL_ELIXIR_OF_DEMONSLAYING:
+ bonus = 50;
+ break;
+ case SPELL_FLASK_OF_THE_FROST_WYRM:
+ bonus = 47;
+ break;
+ case SPELL_WRATH_ELIXIR:
+ bonus = 32;
+ break;
+ case SPELL_ELIXIR_OF_MAJOR_FROST_POWER:
+ case SPELL_ELIXIR_OF_MAJOR_FIREPOWER:
+ case SPELL_ELIXIR_OF_MAJOR_SHADOW_POWER:
+ bonus = 29;
+ break;
+ case SPELL_ELIXIR_OF_MIGHTY_TOUGHTS:
+ bonus = 27;
+ break;
+ case SPELL_FLASK_OF_SUPREME_POWER:
+ case SPELL_FLASK_OF_BLINDING_LIGHT:
+ case SPELL_FLASK_OF_PURE_DEATH:
+ case SPELL_SHADOWPOWER_ELIXIR:
+ bonus = 23;
+ break;
+ case SPELL_ELIXIR_OF_MIGHTY_AGILITY:
+ case SPELL_FLASK_OF_DISTILLED_WISDOM:
+ case SPELL_ELIXIR_OF_SPIRIT:
+ case SPELL_ELIXIR_OF_MIGHTY_STRENGTH:
+ case SPELL_FLASK_OF_PURE_MOJO:
+ case SPELL_ELIXIR_OF_ACCURACY:
+ case SPELL_ELIXIR_OF_DEADLY_STRIKES:
+ case SPELL_ELIXIR_OF_MIGHTY_DEFENSE:
+ case SPELL_ELIXIR_OF_EXPERTISE:
+ case SPELL_ELIXIR_OF_ARMOR_PIERCING:
+ case SPELL_ELIXIR_OF_LIGHTNING_SPEED:
+ bonus = 20;
+ break;
+ case SPELL_FLASK_OF_CHROMATIC_RESISTANCE:
+ bonus = 17;
+ break;
+ case SPELL_ELIXIR_OF_MINOR_FORTITUDE:
+ case SPELL_ELIXIR_OF_MAJOR_STRENGTH:
+ bonus = 15;
+ break;
+ case SPELL_FLASK_OF_MIGHTY_RESTORATION:
+ bonus = 13;
+ break;
+ case SPELL_ARCANE_ELIXIR:
+ bonus = 12;
+ break;
+ case SPELL_ELIXIR_OF_GREATER_AGILITY:
+ case SPELL_ELIXIR_OF_GIANTS:
+ bonus = 11;
+ break;
+ case SPELL_ELIXIR_OF_AGILITY:
+ case SPELL_ELIXIR_OF_GREATER_INTELLECT:
+ case SPELL_ELIXIR_OF_SAGES:
+ case SPELL_ELIXIR_OF_IRONSKIN:
+ case SPELL_ELIXIR_OF_MIGHTY_MAGEBLOOD:
+ bonus = 10;
+ break;
+ case SPELL_ELIXIR_OF_HEALING_POWER:
+ bonus = 9;
+ break;
+ case SPELL_ELIXIR_OF_DRAENIC_WISDOM:
+ case SPELL_GURUS_ELIXIR:
+ bonus = 8;
+ break;
+ case SPELL_ELIXIR_OF_FIREPOWER:
+ case SPELL_ELIXIR_OF_MAJOR_MAGEBLOOD:
+ case SPELL_ELIXIR_OF_MASTERY:
+ bonus = 6;
+ break;
+ case SPELL_ELIXIR_OF_LESSER_AGILITY:
+ case SPELL_ELIXIR_OF_OGRES_STRENGTH:
+ case SPELL_ELIXIR_OF_WISDOM:
+ case SPELL_ELIXIR_OF_THE_MONGOOSE:
+ bonus = 5;
+ break;
+ case SPELL_STRONG_TROLLS_BLOOD_ELIXIR:
+ case SPELL_FLASK_OF_CHROMATIC_WONDER:
+ bonus = 4;
+ break;
+ case SPELL_ELIXIR_OF_EMPOWERMENT:
+ bonus = -10;
+ break;
+ case SPELL_ADEPTS_ELIXIR:
+ SetBonusValueForEffect(EFFECT_0, 13, aurEff);
+ SetBonusValueForEffect(EFFECT_1, 13, aurEff);
+ SetBonusValueForEffect(EFFECT_2, 8, aurEff);
+ break;
+ case SPELL_ELIXIR_OF_MIGHTY_FORTITUDE:
+ SetBonusValueForEffect(EFFECT_0, 160, aurEff);
+ break;
+ case SPELL_ELIXIR_OF_MAJOR_FORTITUDE:
+ SetBonusValueForEffect(EFFECT_0, 116, aurEff);
+ SetBonusValueForEffect(EFFECT_1, 6, aurEff);
+ break;
+ case SPELL_FEL_STRENGTH_ELIXIR:
+ SetBonusValueForEffect(EFFECT_0, 40, aurEff);
+ SetBonusValueForEffect(EFFECT_1, 40, aurEff);
+ break;
+ case SPELL_FLASK_OF_FORTIFICATION:
+ SetBonusValueForEffect(EFFECT_0, 210, aurEff);
+ SetBonusValueForEffect(EFFECT_1, 5, aurEff);
+ break;
+ case SPELL_GREATER_ARCANE_ELIXIR:
+ SetBonusValueForEffect(EFFECT_0, 19, aurEff);
+ SetBonusValueForEffect(EFFECT_1, 19, aurEff);
+ SetBonusValueForEffect(EFFECT_2, 5, aurEff);
+ break;
+ case SPELL_ELIXIR_OF_GIANTH_GROWTH:
+ SetBonusValueForEffect(EFFECT_0, 5, aurEff);
+ break;
+ default:
+ TC_LOG_ERROR("spells", "SpellId %u couldn't be processed in spell_gen_mixology_bonus", GetId());
+ break;
+ }
+ amount += bonus;
}
+ }
- int32 bonus = 0;
-
- void Register() override
- {
- DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_mixology_bonus_AuraScript::CalculateAmount, EFFECT_ALL, SPELL_AURA_ANY);
- }
- };
+ int32 bonus = 0;
- AuraScript* GetAuraScript() const override
+ void Register() override
{
- return new spell_gen_mixology_bonus_AuraScript();
+ DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_mixology_bonus::CalculateAmount, EFFECT_ALL, SPELL_AURA_ANY);
}
};
@@ -4079,71 +3357,49 @@ enum LandmineKnockbackAchievement
SPELL_LANDMINE_KNOCKBACK_ACHIEVEMENT = 57064
};
-class spell_gen_landmine_knockback_achievement : public SpellScriptLoader
+class spell_gen_landmine_knockback_achievement : public SpellScript
{
-public:
- spell_gen_landmine_knockback_achievement() : SpellScriptLoader("spell_gen_landmine_knockback_achievement") { }
+ PrepareSpellScript(spell_gen_landmine_knockback_achievement);
- class spell_gen_landmine_knockback_achievement_SpellScript : public SpellScript
+ void HandleScript(SpellEffIndex /*effIndex*/)
{
- PrepareSpellScript(spell_gen_landmine_knockback_achievement_SpellScript);
-
- void HandleScript(SpellEffIndex /*effIndex*/)
+ if (Player* target = GetHitPlayer())
{
- if (Player* target = GetHitPlayer())
- {
- Aura const* aura = GetHitAura();
- if (!aura || aura->GetStackAmount() < 10)
- return;
-
- target->CastSpell(target, SPELL_LANDMINE_KNOCKBACK_ACHIEVEMENT, true);
- }
- }
+ Aura const* aura = GetHitAura();
+ if (!aura || aura->GetStackAmount() < 10)
+ return;
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_gen_landmine_knockback_achievement_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ target->CastSpell(target, SPELL_LANDMINE_KNOCKBACK_ACHIEVEMENT, true);
}
- };
+ }
- SpellScript* GetSpellScript() const override
+ void Register() override
{
- return new spell_gen_landmine_knockback_achievement_SpellScript();
+ OnEffectHitTarget += SpellEffectFn(spell_gen_landmine_knockback_achievement::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
// 34098 - ClearAllDebuffs
-class spell_gen_clear_debuffs : public SpellScriptLoader
+class spell_gen_clear_debuffs : public SpellScript
{
- public:
- spell_gen_clear_debuffs() : SpellScriptLoader("spell_gen_clear_debuffs") { }
+ PrepareSpellScript(spell_gen_clear_debuffs);
- class spell_gen_clear_debuffs_SpellScript : public SpellScript
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
{
- PrepareSpellScript(spell_gen_clear_debuffs_SpellScript);
-
- void HandleScript(SpellEffIndex /*effIndex*/)
- {
- if (Unit* target = GetHitUnit())
- {
- target->RemoveOwnedAuras([](Aura const* aura)
- {
- SpellInfo const* spellInfo = aura->GetSpellInfo();
- return !spellInfo->IsPositive() && !spellInfo->IsPassive();
- });
- }
- }
-
- void Register() override
+ target->RemoveOwnedAuras([](Aura const* aura)
{
- OnEffectHitTarget += SpellEffectFn(spell_gen_clear_debuffs_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
-
- SpellScript* GetSpellScript() const override
- {
- return new spell_gen_clear_debuffs_SpellScript();
+ SpellInfo const* spellInfo = aura->GetSpellInfo();
+ return !spellInfo->IsPositive() && !spellInfo->IsPassive();
+ });
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_clear_debuffs::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
enum PonySpells
@@ -4152,93 +3408,82 @@ enum PonySpells
MOUNT_PONY = 29736
};
-class spell_gen_pony_mount_check : public SpellScriptLoader
+class spell_gen_pony_mount_check : public AuraScript
{
- public:
- spell_gen_pony_mount_check() : SpellScriptLoader("spell_gen_pony_mount_check") { }
-
- class spell_gen_pony_mount_check_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_pony_mount_check_AuraScript);
-
- void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
- {
- Unit* caster = GetCaster();
- if (!caster)
- return;
- Player* owner = caster->GetOwner()->ToPlayer();
- if (!owner || !owner->HasAchieved(ACHIEV_PONY_UP))
- return;
-
- if (owner->IsMounted())
- {
- caster->Mount(MOUNT_PONY);
- caster->SetSpeedRate(MOVE_RUN, owner->GetSpeedRate(MOVE_RUN));
- }
- else if (caster->IsMounted())
- {
- caster->Dismount();
- caster->SetSpeedRate(MOVE_RUN, owner->GetSpeedRate(MOVE_RUN));
- }
- }
+ PrepareAuraScript(spell_gen_pony_mount_check);
- void Register() override
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_gen_pony_mount_check_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
- }
- };
+ void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
+ {
+ Unit* caster = GetCaster();
+ if (!caster)
+ return;
+ Player* owner = caster->GetOwner()->ToPlayer();
+ if (!owner || !owner->HasAchieved(ACHIEV_PONY_UP))
+ return;
- AuraScript* GetAuraScript() const
+ if (owner->IsMounted())
+ {
+ caster->Mount(MOUNT_PONY);
+ caster->SetSpeedRate(MOVE_RUN, owner->GetSpeedRate(MOVE_RUN));
+ }
+ else if (caster->IsMounted())
{
- return new spell_gen_pony_mount_check_AuraScript();
+ caster->Dismount();
+ caster->SetSpeedRate(MOVE_RUN, owner->GetSpeedRate(MOVE_RUN));
}
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_gen_pony_mount_check::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
};
void AddSC_generic_spell_scripts()
{
- new spell_gen_absorb0_hitlimit1();
- new spell_gen_adaptive_warding();
- new spell_gen_allow_cast_from_item_only();
- new spell_gen_animal_blood();
- new spell_gen_aura_of_anger();
- new spell_gen_aura_service_uniform();
- new spell_gen_av_drekthar_presence();
- new spell_gen_bandage();
- new spell_gen_blood_reserve();
- new spell_gen_blade_warding();
- new spell_gen_bonked();
+ RegisterAuraScript(spell_gen_absorb0_hitlimit1);
+ RegisterAuraScript(spell_gen_adaptive_warding);
+ RegisterSpellScript(spell_gen_allow_cast_from_item_only);
+ RegisterAuraScript(spell_gen_animal_blood);
+ RegisterAuraScript(spell_gen_aura_of_anger);
+ RegisterAuraScript(spell_gen_aura_service_uniform);
+ RegisterAuraScript(spell_gen_av_drekthar_presence);
+ RegisterSpellScript(spell_gen_bandage);
+ RegisterAuraScript(spell_gen_blood_reserve);
+ RegisterAuraScript(spell_gen_blade_warding);
+ RegisterSpellScript(spell_gen_bonked);
new spell_gen_break_shield("spell_gen_break_shield");
new spell_gen_break_shield("spell_gen_tournament_counterattack");
- new spell_gen_burn_brutallus();
- new spell_gen_burning_depths_necrolyte_image();
- new spell_gen_cannibalize();
- new spell_gen_chaos_blast();
- new spell_gen_clone();
- new spell_gen_clone_weapon();
- new spell_gen_clone_weapon_aura();
+ RegisterAuraScript(spell_gen_burn_brutallus);
+ RegisterAuraScript(spell_gen_burning_depths_necrolyte_image);
+ RegisterSpellScript(spell_gen_cannibalize);
+ RegisterSpellScript(spell_gen_chaos_blast);
+ RegisterSpellScript(spell_gen_clone);
+ RegisterSpellScript(spell_gen_clone_weapon);
+ RegisterAuraScript(spell_gen_clone_weapon_aura);
new spell_gen_count_pct_from_max_hp("spell_gen_default_count_pct_from_max_hp");
new spell_gen_count_pct_from_max_hp("spell_gen_50pct_count_pct_from_max_hp", 50);
- new spell_gen_create_lance();
- new spell_gen_creature_permanent_feign_death();
+ RegisterSpellScript(spell_gen_create_lance);
+ RegisterAuraScript(spell_gen_creature_permanent_feign_death);
new spell_gen_dalaran_disguise("spell_gen_sunreaver_disguise");
new spell_gen_dalaran_disguise("spell_gen_silver_covenant_disguise");
- new spell_gen_damage_reduction_aura();
- new spell_gen_defend();
- new spell_gen_despawn_self();
- new spell_gen_divine_storm_cd_reset();
- new spell_gen_ds_flush_knockback();
- new spell_gen_dungeon_credit();
- new spell_gen_elune_candle();
- new spell_gen_gadgetzan_transporter_backfire();
- new spell_gen_gift_of_naaru();
- new spell_gen_gnomish_transporter();
- new spell_gen_lifeblood();
+ RegisterAuraScript(spell_gen_damage_reduction_aura);
+ RegisterAuraScript(spell_gen_defend);
+ RegisterSpellScript(spell_gen_despawn_self);
+ RegisterSpellScript(spell_gen_divine_storm_cd_reset);
+ RegisterSpellScript(spell_gen_ds_flush_knockback);
+ RegisterSpellScript(spell_gen_dungeon_credit);
+ RegisterSpellScript(spell_gen_elune_candle);
+ RegisterSpellScript(spell_gen_gadgetzan_transporter_backfire);
+ RegisterAuraScript(spell_gen_gift_of_naaru);
+ RegisterSpellScript(spell_gen_gnomish_transporter);
+ RegisterAuraScript(spell_gen_lifeblood);
new spell_gen_lifebloom("spell_hexlord_lifebloom", SPELL_HEXLORD_MALACRASS_LIFEBLOOM_FINAL_HEAL);
new spell_gen_lifebloom("spell_tur_ragepaw_lifebloom", SPELL_TUR_RAGEPAW_LIFEBLOOM_FINAL_HEAL);
new spell_gen_lifebloom("spell_cenarion_scout_lifebloom", SPELL_CENARION_SCOUT_LIFEBLOOM_FINAL_HEAL);
new spell_gen_lifebloom("spell_twisted_visage_lifebloom", SPELL_TWISTED_VISAGE_LIFEBLOOM_FINAL_HEAL);
new spell_gen_lifebloom("spell_faction_champion_dru_lifebloom", SPELL_FACTION_CHAMPIONS_DRU_LIFEBLOOM_FINAL_HEAL);
- new spell_gen_magic_rooster();
+ RegisterSpellScript(spell_gen_magic_rooster);
new spell_gen_mount("spell_magic_broom", 0, SPELL_MAGIC_BROOM_60, SPELL_MAGIC_BROOM_100, SPELL_MAGIC_BROOM_150, SPELL_MAGIC_BROOM_280);
new spell_gen_mount("spell_headless_horseman_mount", 0, SPELL_HEADLESS_HORSEMAN_MOUNT_60, SPELL_HEADLESS_HORSEMAN_MOUNT_100, SPELL_HEADLESS_HORSEMAN_MOUNT_150, SPELL_HEADLESS_HORSEMAN_MOUNT_280);
new spell_gen_mount("spell_winged_steed_of_the_ebon_blade", 0, 0, 0, SPELL_WINGED_STEED_150, SPELL_WINGED_STEED_280);
@@ -4248,50 +3493,50 @@ void AddSC_generic_spell_scripts()
new spell_gen_mount("spell_blazing_hippogryph", 0, 0, 0, SPELL_BLAZING_HIPPOGRYPH_150, SPELL_BLAZING_HIPPOGRYPH_280);
new spell_gen_mount("spell_celestial_steed", 0, SPELL_CELESTIAL_STEED_60, SPELL_CELESTIAL_STEED_100, SPELL_CELESTIAL_STEED_150, SPELL_CELESTIAL_STEED_280, SPELL_CELESTIAL_STEED_310);
new spell_gen_mount("spell_x53_touring_rocket", 0, 0, 0, SPELL_X53_TOURING_ROCKET_150, SPELL_X53_TOURING_ROCKET_280, SPELL_X53_TOURING_ROCKET_310);
- new spell_gen_mounted_charge();
- new spell_gen_moss_covered_feet();
- new spell_gen_netherbloom();
- new spell_gen_nightmare_vine();
- new spell_gen_obsidian_armor();
- new spell_gen_oracle_wolvar_reputation();
- new spell_gen_orc_disguise();
- new spell_gen_paralytic_poison();
+ RegisterSpellScript(spell_gen_mounted_charge);
+ RegisterAuraScript(spell_gen_moss_covered_feet);
+ RegisterSpellScript(spell_gen_netherbloom);
+ RegisterSpellScript(spell_gen_nightmare_vine);
+ RegisterAuraScript(spell_gen_obsidian_armor);
+ RegisterSpellScript(spell_gen_oracle_wolvar_reputation);
+ RegisterSpellScript(spell_gen_orc_disguise);
+ RegisterAuraScript(spell_gen_paralytic_poison);
new spell_gen_proc_below_pct_damaged("spell_item_soul_harvesters_charm");
new spell_gen_proc_below_pct_damaged("spell_item_commendation_of_kaelthas");
new spell_gen_proc_below_pct_damaged("spell_item_corpse_tongue_coin");
new spell_gen_proc_below_pct_damaged("spell_item_corpse_tongue_coin_heroic");
new spell_gen_proc_below_pct_damaged("spell_item_petrified_twilight_scale");
new spell_gen_proc_below_pct_damaged("spell_item_petrified_twilight_scale_heroic");
- new spell_gen_proc_charge_drop_only();
- new spell_gen_parachute();
- new spell_gen_pet_summoned();
- new spell_gen_profession_research();
- new spell_gen_remove_flight_auras();
- new spell_gen_replenishment();
- new spell_gen_seaforium_blast();
- new spell_gen_spectator_cheer_trigger();
- new spell_gen_spirit_healer_res();
+ RegisterAuraScript(spell_gen_proc_charge_drop_only);
+ RegisterAuraScript(spell_gen_parachute);
+ RegisterSpellScript(spell_gen_pet_summoned);
+ RegisterSpellScript(spell_gen_profession_research);
+ RegisterSpellScript(spell_gen_remove_flight_auras);
+ RegisterSpellAndAuraScriptPair(spell_gen_replenishment, spell_gen_replenishment_aura);
+ RegisterSpellScript(spell_gen_seaforium_blast);
+ RegisterSpellScript(spell_gen_spectator_cheer_trigger);
+ RegisterSpellScript(spell_gen_spirit_healer_res);
new spell_gen_summon_elemental("spell_gen_summon_fire_elemental", SPELL_SUMMON_FIRE_ELEMENTAL);
new spell_gen_summon_elemental("spell_gen_summon_earth_elemental", SPELL_SUMMON_EARTH_ELEMENTAL);
- new spell_gen_summon_tournament_mount();
- new spell_gen_throw_shield();
- new spell_gen_tournament_duel();
- new spell_gen_tournament_pennant();
+ RegisterSpellScript(spell_gen_summon_tournament_mount);
+ RegisterSpellScript(spell_gen_throw_shield);
+ RegisterSpellScript(spell_gen_tournament_duel);
+ RegisterAuraScript(spell_gen_tournament_pennant);
new spell_pvp_trinket_wotf_shared_cd<SPELL_WILL_OF_THE_FORSAKEN_COOLDOWN_TRIGGER>("spell_pvp_trinket_shared_cd");
new spell_pvp_trinket_wotf_shared_cd<SPELL_WILL_OF_THE_FORSAKEN_COOLDOWN_TRIGGER_WOTF>("spell_wotf_shared_cd");
- new spell_gen_turkey_marker();
- new spell_gen_upper_deck_create_foam_sword();
- new spell_gen_vampiric_touch();
- new spell_gen_vehicle_scaling();
- new spell_gen_vendor_bark_trigger();
- new spell_gen_wg_water();
- new spell_gen_whisper_gulch_yogg_saron_whisper();
- new spell_gen_eject_all_passengers();
- new spell_gen_eject_passenger();
- new spell_gen_gm_freeze();
- new spell_gen_stand();
- new spell_gen_mixology_bonus();
- new spell_gen_landmine_knockback_achievement();
- new spell_gen_clear_debuffs();
- new spell_gen_pony_mount_check();
+ RegisterAuraScript(spell_gen_turkey_marker);
+ RegisterSpellScript(spell_gen_upper_deck_create_foam_sword);
+ RegisterAuraScript(spell_gen_vampiric_touch);
+ RegisterAuraScript(spell_gen_vehicle_scaling);
+ RegisterSpellScript(spell_gen_vendor_bark_trigger);
+ RegisterSpellScript(spell_gen_wg_water);
+ RegisterAuraScript(spell_gen_whisper_gulch_yogg_saron_whisper);
+ RegisterSpellScript(spell_gen_eject_all_passengers);
+ RegisterSpellScript(spell_gen_eject_passenger);
+ RegisterAuraScript(spell_gen_gm_freeze);
+ RegisterSpellScript(spell_gen_stand);
+ RegisterAuraScript(spell_gen_mixology_bonus);
+ RegisterSpellScript(spell_gen_landmine_knockback_achievement);
+ RegisterSpellScript(spell_gen_clear_debuffs);
+ RegisterAuraScript(spell_gen_pony_mount_check);
}
diff --git a/src/server/scripts/Spells/spell_holiday.cpp b/src/server/scripts/Spells/spell_holiday.cpp
index eac0ff10c23..8c395077c96 100644
--- a/src/server/scripts/Spells/spell_holiday.cpp
+++ b/src/server/scripts/Spells/spell_holiday.cpp
@@ -921,14 +921,14 @@ class spell_pilgrims_bounty_a_serving_of : public SpellScriptLoader
void OnApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
- target->CastSpell(target, uint32(aurEff->GetBaseAmount()), true);
+ target->CastSpell(target, uint32(aurEff->GetAmount()), true);
HandlePlate(target, true);
}
void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
- target->RemoveAurasDueToSpell(aurEff->GetBaseAmount());
+ target->RemoveAurasDueToSpell(aurEff->GetAmount());
HandlePlate(target, false);
}
@@ -1318,7 +1318,7 @@ class spell_brewfest_relay_race_intro_force_player_to_throw : public SpellScript
PreventHitDefaultEffect(effIndex);
// All this spells trigger a spell that requires reagents; if the
// triggered spell is cast as "triggered", reagents are not consumed
- GetHitUnit()->CastSpell((Unit*)nullptr, GetSpellInfo()->Effects[effIndex].TriggerSpell, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST));
+ GetHitUnit()->CastSpell(nullptr, GetSpellInfo()->Effects[effIndex].TriggerSpell, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST));
}
void Register() override
@@ -1489,117 +1489,175 @@ enum TorchSpells
SPELL_TORCH_TOSSING_PRACTICE = 46630,
SPELL_TORCH_TOSSING_TRAINING_SUCCESS_ALLIANCE = 45719,
SPELL_TORCH_TOSSING_TRAINING_SUCCESS_HORDE = 46651,
+ SPELL_TARGET_INDICATOR_COSMETIC = 46901,
+ SPELL_TARGET_INDICATOR = 45723,
SPELL_BRAZIERS_HIT = 45724
};
// 45724 - Braziers Hit!
-class spell_midsummer_braziers_hit : public SpellScriptLoader
+class spell_midsummer_braziers_hit : public AuraScript
{
- public:
- spell_midsummer_braziers_hit() : SpellScriptLoader("spell_midsummer_braziers_hit") { }
+ PrepareAuraScript(spell_midsummer_braziers_hit);
- class spell_midsummer_braziers_hit_AuraScript : public AuraScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareAuraScript(spell_midsummer_braziers_hit_AuraScript);
+ SPELL_TORCH_TOSSING_TRAINING,
+ SPELL_TORCH_TOSSING_PRACTICE,
+ SPELL_TORCH_TOSSING_TRAINING_SUCCESS_ALLIANCE,
+ SPELL_TORCH_TOSSING_TRAINING_SUCCESS_HORDE
+ });
+ }
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_TORCH_TOSSING_TRAINING, SPELL_TORCH_TOSSING_PRACTICE });
- }
+ void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Player* player = GetTarget()->ToPlayer();
+ if (!player)
+ return;
- void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- Player* player = GetTarget()->ToPlayer();
- if (!player)
- return;
+ if ((player->HasAura(SPELL_TORCH_TOSSING_TRAINING) && GetStackAmount() == 8) || (player->HasAura(SPELL_TORCH_TOSSING_PRACTICE) && GetStackAmount() == 20))
+ {
+ if (player->GetTeam() == ALLIANCE)
+ player->CastSpell(player, SPELL_TORCH_TOSSING_TRAINING_SUCCESS_ALLIANCE, true);
+ else if (player->GetTeam() == HORDE)
+ player->CastSpell(player, SPELL_TORCH_TOSSING_TRAINING_SUCCESS_HORDE, true);
+ Remove();
+ }
+ }
- if ((player->HasAura(SPELL_TORCH_TOSSING_TRAINING) && GetStackAmount() == 8) || (player->HasAura(SPELL_TORCH_TOSSING_PRACTICE) && GetStackAmount() == 20))
- {
- if (player->GetTeam() == ALLIANCE)
- player->CastSpell(player, SPELL_TORCH_TOSSING_TRAINING_SUCCESS_ALLIANCE, true);
- else if (player->GetTeam() == HORDE)
- player->CastSpell(player, SPELL_TORCH_TOSSING_TRAINING_SUCCESS_HORDE, true);
- Remove();
- }
- }
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_midsummer_braziers_hit::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAPPLY);
+ }
+};
- void Register() override
- {
- AfterEffectApply += AuraEffectApplyFn(spell_midsummer_braziers_hit_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AuraEffectHandleModes(AURA_EFFECT_HANDLE_REAPPLY));
- }
- };
+// 45907 - Torch Target Picker
+class spell_midsummer_torch_target_picker : public SpellScript
+{
+ PrepareSpellScript(spell_midsummer_torch_target_picker);
- AuraScript* GetAuraScript() const override
- {
- return new spell_midsummer_braziers_hit_AuraScript();
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_TARGET_INDICATOR_COSMETIC, SPELL_TARGET_INDICATOR });
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Unit* target = GetHitUnit();
+ target->CastSpell(target, SPELL_TARGET_INDICATOR_COSMETIC, true);
+ target->CastSpell(target, SPELL_TARGET_INDICATOR, true);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_midsummer_torch_target_picker::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+};
+
+// 46054 - Torch Toss (land)
+class spell_midsummer_torch_toss_land : public SpellScript
+{
+ PrepareSpellScript(spell_midsummer_torch_toss_land);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_BRAZIERS_HIT });
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ GetHitUnit()->CastSpell(GetCaster(), SPELL_BRAZIERS_HIT, true);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_midsummer_torch_toss_land::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
enum RibbonPoleData
{
- SPELL_HAS_FULL_MIDSUMMER_SET = 58933,
- SPELL_BURNING_HOT_POLE_DANCE = 58934,
- SPELL_RIBBON_DANCE_COSMETIC = 29726,
- SPELL_RIBBON_DANCE = 29175,
- GO_RIBBON_POLE = 181605,
+ SPELL_HAS_FULL_MIDSUMMER_SET = 58933,
+ SPELL_BURNING_HOT_POLE_DANCE = 58934,
+ SPELL_RIBBON_POLE_PERIODIC_VISUAL = 45406,
+ SPELL_RIBBON_DANCE = 29175,
+ SPELL_TEST_RIBBON_POLE_1 = 29705,
+ SPELL_TEST_RIBBON_POLE_2 = 29726,
+ SPELL_TEST_RIBBON_POLE_3 = 29727
};
-class spell_gen_ribbon_pole_dancer_check : public SpellScriptLoader
+// 29705, 29726, 29727 - Test Ribbon Pole Channel
+class spell_midsummer_test_ribbon_pole_channel : public AuraScript
{
- public:
- spell_gen_ribbon_pole_dancer_check() : SpellScriptLoader("spell_gen_ribbon_pole_dancer_check") { }
+ PrepareAuraScript(spell_midsummer_test_ribbon_pole_channel);
- class spell_gen_ribbon_pole_dancer_check_AuraScript : public AuraScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareAuraScript(spell_gen_ribbon_pole_dancer_check_AuraScript);
+ SPELL_RIBBON_POLE_PERIODIC_VISUAL,
+ SPELL_BURNING_HOT_POLE_DANCE,
+ SPELL_HAS_FULL_MIDSUMMER_SET,
+ SPELL_RIBBON_DANCE
+ });
+ }
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_HAS_FULL_MIDSUMMER_SET,
- SPELL_RIBBON_DANCE,
- SPELL_BURNING_HOT_POLE_DANCE
- });
- }
+ void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->RemoveAurasDueToSpell(SPELL_RIBBON_POLE_PERIODIC_VISUAL);
+ }
- void PeriodicTick(AuraEffect const* /*aurEff*/)
- {
- Unit* target = GetTarget();
+ void PeriodicTick(AuraEffect const* /*aurEff*/)
+ {
+ Unit* target = GetTarget();
+ target->CastSpell(target, SPELL_RIBBON_POLE_PERIODIC_VISUAL, true);
- // check if aura needs to be removed
- if (!target->FindNearestGameObject(GO_RIBBON_POLE, 8.0f) || !target->HasUnitState(UNIT_STATE_CASTING))
- {
- target->InterruptNonMeleeSpells(false);
- target->RemoveAurasDueToSpell(GetId());
- target->RemoveAura(SPELL_RIBBON_DANCE_COSMETIC);
- return;
- }
+ if (Aura* aur = target->GetAura(SPELL_RIBBON_DANCE))
+ {
+ aur->SetMaxDuration(std::min(3600000, aur->GetMaxDuration() + 180000));
+ aur->RefreshDuration();
- // set xp buff duration
- if (Aura* aur = target->GetAura(SPELL_RIBBON_DANCE))
- {
- aur->SetMaxDuration(std::min(3600000, aur->GetMaxDuration() + 180000));
- aur->RefreshDuration();
+ if (aur->GetMaxDuration() == 3600000 && target->HasAura(SPELL_HAS_FULL_MIDSUMMER_SET))
+ target->CastSpell(target, SPELL_BURNING_HOT_POLE_DANCE, true);
+ }
+ else
+ target->CastSpell(target, SPELL_RIBBON_DANCE, true);
+ }
- // reward achievement criteria
- if (aur->GetMaxDuration() == 3600000 && target->HasAura(SPELL_HAS_FULL_MIDSUMMER_SET))
- target->CastSpell(target, SPELL_BURNING_HOT_POLE_DANCE, true);
- }
- else
- target->AddAura(SPELL_RIBBON_DANCE, target);
- }
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_midsummer_test_ribbon_pole_channel::HandleRemove, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_midsummer_test_ribbon_pole_channel::PeriodicTick, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
+};
- void Register() override
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_gen_ribbon_pole_dancer_check_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
- }
- };
+// 45406 - Holiday - Midsummer, Ribbon Pole Periodic Visual
+class spell_midsummer_ribbon_pole_periodic_visual : public AuraScript
+{
+ PrepareAuraScript(spell_midsummer_ribbon_pole_periodic_visual);
- AuraScript* GetAuraScript() const override
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- return new spell_gen_ribbon_pole_dancer_check_AuraScript();
- }
+ SPELL_TEST_RIBBON_POLE_1,
+ SPELL_TEST_RIBBON_POLE_2,
+ SPELL_TEST_RIBBON_POLE_3
+ });
+ }
+
+ void PeriodicTick(AuraEffect const* /*aurEff*/)
+ {
+ Unit* target = GetTarget();
+ if (!target->HasAura(SPELL_TEST_RIBBON_POLE_1) && !target->HasAura(SPELL_TEST_RIBBON_POLE_2) && !target->HasAura(SPELL_TEST_RIBBON_POLE_3))
+ Remove();
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_midsummer_ribbon_pole_periodic_visual::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
};
void AddSC_holiday_spell_scripts()
@@ -1650,6 +1708,9 @@ void AddSC_holiday_spell_scripts()
new spell_brewfest_dismount_ram();
new spell_brewfest_barker_bunny();
// Midsummer Fire Festival
- new spell_midsummer_braziers_hit();
- new spell_gen_ribbon_pole_dancer_check();
+ RegisterAuraScript(spell_midsummer_braziers_hit);
+ RegisterSpellScript(spell_midsummer_torch_target_picker);
+ RegisterSpellScript(spell_midsummer_torch_toss_land);
+ RegisterAuraScript(spell_midsummer_test_ribbon_pole_channel);
+ RegisterAuraScript(spell_midsummer_ribbon_pole_periodic_visual);
}
diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp
index 2b9bfac79e9..a7fed99dccf 100644
--- a/src/server/scripts/Spells/spell_hunter.cpp
+++ b/src/server/scripts/Spells/spell_hunter.cpp
@@ -443,7 +443,7 @@ class spell_hun_glyph_of_mend_pet : public SpellScriptLoader
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetProcTarget()->CastSpell((Unit*)nullptr, SPELL_HUNTER_GLYPH_OF_MEND_PET_HAPPINESS, true, nullptr, aurEff);
+ eventInfo.GetProcTarget()->CastSpell(nullptr, SPELL_HUNTER_GLYPH_OF_MEND_PET_HAPPINESS, true, nullptr, aurEff);
}
void Register() override
@@ -476,7 +476,7 @@ class spell_hun_hunting_party : public SpellScriptLoader
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_REPLENISHMENT, true, nullptr, aurEff);
+ eventInfo.GetActor()->CastSpell(nullptr, SPELL_REPLENISHMENT, true, nullptr, aurEff);
}
void Register() override
@@ -775,7 +775,7 @@ class spell_hun_masters_call : public SpellScriptLoader
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
{
- GetHitUnit()->CastSpell((Unit*)nullptr, SPELL_HUNTER_MASTERS_CALL_TRIGGERED, true);
+ GetHitUnit()->CastSpell(nullptr, SPELL_HUNTER_MASTERS_CALL_TRIGGERED, true);
}
void Register() override
@@ -1105,7 +1105,7 @@ class spell_hun_rapid_recuperation_trigger : public SpellScriptLoader
uint8 rank = GetSpellInfo()->GetRank();
uint32 spellId = triggerSpells[rank - 1];
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, spellId, true, nullptr, aurEff);
+ eventInfo.GetActor()->CastSpell(nullptr, spellId, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp
index 0de0c0c00b9..e78bd3804be 100644
--- a/src/server/scripts/Spells/spell_item.cpp
+++ b/src/server/scripts/Spells/spell_item.cpp
@@ -85,36 +85,25 @@ enum AegisOfPreservation
};
// 23780 - Aegis of Preservation
-class spell_item_aegis_of_preservation : public SpellScriptLoader
+class spell_item_aegis_of_preservation : public AuraScript
{
- public:
- spell_item_aegis_of_preservation() : SpellScriptLoader("spell_item_aegis_of_preservation") { }
-
- class spell_item_aegis_of_preservation_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_aegis_of_preservation_AuraScript);
+ PrepareAuraScript(spell_item_aegis_of_preservation);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_AEGIS_HEAL });
- }
-
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
- {
- PreventDefaultAction();
- GetTarget()->CastSpell(GetTarget(), SPELL_AEGIS_HEAL, true, nullptr, aurEff);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_AEGIS_HEAL });
+ }
- void Register() override
- {
- OnEffectProc += AuraEffectProcFn(spell_item_aegis_of_preservation_AuraScript::HandleProc, EFFECT_1, SPELL_AURA_PROC_TRIGGER_SPELL);
- }
- };
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
+ {
+ PreventDefaultAction();
+ GetTarget()->CastSpell(GetTarget(), SPELL_AEGIS_HEAL, true, nullptr, aurEff);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_aegis_of_preservation_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_item_aegis_of_preservation::HandleProc, EFFECT_1, SPELL_AURA_PROC_TRIGGER_SPELL);
+ }
};
enum AlchemistStone
@@ -133,62 +122,51 @@ enum AlchemistStone
// Item - 44324: Mighty Alchemist's Stone
// 17619 - Alchemist's Stone
-class spell_item_alchemists_stone : public SpellScriptLoader
+class spell_item_alchemists_stone : public AuraScript
{
- public:
- spell_item_alchemists_stone() : SpellScriptLoader("spell_item_alchemists_stone") { }
+ PrepareAuraScript(spell_item_alchemists_stone);
- class spell_item_alchemists_stone_AuraScript : public AuraScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareAuraScript(spell_item_alchemists_stone_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_ALCHEMISTS_STONE_EXTRA_HEAL,
- SPELL_ALCHEMISTS_STONE_EXTRA_MANA
- });
- }
-
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
- SpellInfo const* spellInfo = eventInfo.GetSpellInfo();
- if (!spellInfo)
- return;
+ SPELL_ALCHEMISTS_STONE_EXTRA_HEAL,
+ SPELL_ALCHEMISTS_STONE_EXTRA_MANA
+ });
+ }
- Unit* caster = eventInfo.GetActionTarget();
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- {
- uint32 spellId;
- switch (spellInfo->Effects[i].Effect)
- {
- case SPELL_EFFECT_HEAL:
- spellId = SPELL_ALCHEMISTS_STONE_EXTRA_HEAL;
- break;
- case SPELL_EFFECT_ENERGIZE:
- spellId = SPELL_ALCHEMISTS_STONE_EXTRA_MANA;
- break;
- default:
- continue;
- }
-
- int32 amount = CalculatePct(spellInfo->Effects[i].CalcValue(caster), 40);
- caster->CastCustomSpell(spellId, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff);
- }
- }
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+ SpellInfo const* spellInfo = eventInfo.GetSpellInfo();
+ if (!spellInfo)
+ return;
- void Register() override
+ Unit* caster = eventInfo.GetActionTarget();
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ uint32 spellId;
+ switch (spellInfo->Effects[i].Effect)
{
- OnEffectProc += AuraEffectProcFn(spell_item_alchemists_stone_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
+ case SPELL_EFFECT_HEAL:
+ spellId = SPELL_ALCHEMISTS_STONE_EXTRA_HEAL;
+ break;
+ case SPELL_EFFECT_ENERGIZE:
+ spellId = SPELL_ALCHEMISTS_STONE_EXTRA_MANA;
+ break;
+ default:
+ continue;
}
- };
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_alchemists_stone_AuraScript();
+ int32 amount = CalculatePct(spellInfo->Effects[i].CalcValue(caster), 40);
+ caster->CastCustomSpell(spellId, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff);
}
+ }
+
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_item_alchemists_stone::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
+ }
};
enum AngerCapacitor
@@ -230,7 +208,7 @@ class spell_item_anger_capacitor : public SpellScriptLoader
Unit* caster = eventInfo.GetActor();
Unit* target = eventInfo.GetProcTarget();
- caster->CastSpell((Unit*)nullptr, SPELL_MOTE_OF_ANGER, true);
+ caster->CastSpell(nullptr, SPELL_MOTE_OF_ANGER, true);
Aura const* motes = caster->GetAura(SPELL_MOTE_OF_ANGER);
if (!motes || motes->GetStackAmount() < Stacks)
return;
@@ -257,32 +235,21 @@ class spell_item_anger_capacitor : public SpellScriptLoader
};
// 26400 - Arcane Shroud
-class spell_item_arcane_shroud : public SpellScriptLoader
+class spell_item_arcane_shroud : public AuraScript
{
- public:
- spell_item_arcane_shroud() : SpellScriptLoader("spell_item_arcane_shroud") { }
-
- class spell_item_arcane_shroud_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_arcane_shroud_AuraScript);
+ PrepareAuraScript(spell_item_arcane_shroud);
- void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
- {
- int32 diff = GetUnitOwner()->getLevel() - 60;
- if (diff > 0)
- amount += 2 * diff;
- }
-
- void Register() override
- {
- DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_item_arcane_shroud_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_THREAT);
- }
- };
+ void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
+ {
+ int32 diff = GetUnitOwner()->getLevel() - 60;
+ if (diff > 0)
+ amount += 2 * diff;
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_arcane_shroud_AuraScript();
- }
+ void Register() override
+ {
+ DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_item_arcane_shroud::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_THREAT);
+ }
};
enum AuraOfMadness
@@ -305,117 +272,95 @@ enum AuraOfMadness
// Item - 31859: Darkmoon Card: Madness
// 39446 - Aura of Madness
-class spell_item_aura_of_madness : public SpellScriptLoader
+class spell_item_aura_of_madness : public AuraScript
{
- public:
- spell_item_aura_of_madness() : SpellScriptLoader("spell_item_aura_of_madness") { }
-
- class spell_item_aura_of_madness_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_aura_of_madness_AuraScript);
+ PrepareAuraScript(spell_item_aura_of_madness);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_SOCIOPATH,
- SPELL_DELUSIONAL,
- SPELL_KLEPTOMANIA,
- SPELL_MEGALOMANIA,
- SPELL_PARANOIA,
- SPELL_MANIC,
- SPELL_NARCISSISM,
- SPELL_MARTYR_COMPLEX,
- SPELL_DEMENTIA
- }) && sObjectMgr->GetBroadcastText(SAY_MADNESS);
- }
-
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- static std::vector<uint32> const triggeredSpells[MAX_CLASSES] =
- {
- //CLASS_NONE
- { },
- //CLASS_WARRIOR
- { SPELL_SOCIOPATH, SPELL_DELUSIONAL, SPELL_KLEPTOMANIA, SPELL_PARANOIA, SPELL_MANIC, SPELL_MARTYR_COMPLEX },
- //CLASS_PALADIN
- { SPELL_SOCIOPATH, SPELL_DELUSIONAL, SPELL_KLEPTOMANIA, SPELL_MEGALOMANIA, SPELL_PARANOIA, SPELL_MANIC, SPELL_NARCISSISM, SPELL_MARTYR_COMPLEX, SPELL_DEMENTIA },
- //CLASS_HUNTER
- { SPELL_DELUSIONAL, SPELL_MEGALOMANIA, SPELL_PARANOIA, SPELL_MANIC, SPELL_NARCISSISM, SPELL_MARTYR_COMPLEX, SPELL_DEMENTIA },
- //CLASS_ROGUE
- { SPELL_SOCIOPATH, SPELL_DELUSIONAL, SPELL_KLEPTOMANIA, SPELL_PARANOIA, SPELL_MANIC, SPELL_MARTYR_COMPLEX },
- //CLASS_PRIEST
- { SPELL_MEGALOMANIA, SPELL_PARANOIA, SPELL_MANIC, SPELL_NARCISSISM, SPELL_MARTYR_COMPLEX, SPELL_DEMENTIA },
- //CLASS_DEATH_KNIGHT
- { SPELL_SOCIOPATH, SPELL_DELUSIONAL, SPELL_KLEPTOMANIA, SPELL_PARANOIA, SPELL_MANIC, SPELL_MARTYR_COMPLEX },
- //CLASS_SHAMAN
- { SPELL_MEGALOMANIA, SPELL_PARANOIA, SPELL_MANIC, SPELL_NARCISSISM, SPELL_MARTYR_COMPLEX, SPELL_DEMENTIA },
- //CLASS_MAGE
- { SPELL_MEGALOMANIA, SPELL_PARANOIA, SPELL_MANIC, SPELL_NARCISSISM, SPELL_MARTYR_COMPLEX, SPELL_DEMENTIA },
- //CLASS_WARLOCK
- { SPELL_MEGALOMANIA, SPELL_PARANOIA, SPELL_MANIC, SPELL_NARCISSISM, SPELL_MARTYR_COMPLEX, SPELL_DEMENTIA },
- //CLASS_UNK
- { },
- //CLASS_DRUID
- { SPELL_SOCIOPATH, SPELL_DELUSIONAL, SPELL_KLEPTOMANIA, SPELL_MEGALOMANIA, SPELL_PARANOIA, SPELL_MANIC, SPELL_NARCISSISM, SPELL_MARTYR_COMPLEX, SPELL_DEMENTIA }
- };
-
- PreventDefaultAction();
- Unit* caster = eventInfo.GetActor();
- uint32 spellId = Trinity::Containers::SelectRandomContainerElement(triggeredSpells[caster->getClass()]);
- caster->CastSpell(caster, spellId, true, nullptr, aurEff);
-
- if (roll_chance_i(10))
- caster->Unit::Say(SAY_MADNESS);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
+ {
+ SPELL_SOCIOPATH,
+ SPELL_DELUSIONAL,
+ SPELL_KLEPTOMANIA,
+ SPELL_MEGALOMANIA,
+ SPELL_PARANOIA,
+ SPELL_MANIC,
+ SPELL_NARCISSISM,
+ SPELL_MARTYR_COMPLEX,
+ SPELL_DEMENTIA
+ }) && sObjectMgr->GetBroadcastText(SAY_MADNESS);
+ }
- void Register() override
- {
- OnEffectProc += AuraEffectProcFn(spell_item_aura_of_madness_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
- }
- };
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ static std::vector<uint32> const triggeredSpells[MAX_CLASSES] =
+ {
+ //CLASS_NONE
+ { },
+ //CLASS_WARRIOR
+ { SPELL_SOCIOPATH, SPELL_DELUSIONAL, SPELL_KLEPTOMANIA, SPELL_PARANOIA, SPELL_MANIC, SPELL_MARTYR_COMPLEX },
+ //CLASS_PALADIN
+ { SPELL_SOCIOPATH, SPELL_DELUSIONAL, SPELL_KLEPTOMANIA, SPELL_MEGALOMANIA, SPELL_PARANOIA, SPELL_MANIC, SPELL_NARCISSISM, SPELL_MARTYR_COMPLEX, SPELL_DEMENTIA },
+ //CLASS_HUNTER
+ { SPELL_DELUSIONAL, SPELL_MEGALOMANIA, SPELL_PARANOIA, SPELL_MANIC, SPELL_NARCISSISM, SPELL_MARTYR_COMPLEX, SPELL_DEMENTIA },
+ //CLASS_ROGUE
+ { SPELL_SOCIOPATH, SPELL_DELUSIONAL, SPELL_KLEPTOMANIA, SPELL_PARANOIA, SPELL_MANIC, SPELL_MARTYR_COMPLEX },
+ //CLASS_PRIEST
+ { SPELL_MEGALOMANIA, SPELL_PARANOIA, SPELL_MANIC, SPELL_NARCISSISM, SPELL_MARTYR_COMPLEX, SPELL_DEMENTIA },
+ //CLASS_DEATH_KNIGHT
+ { SPELL_SOCIOPATH, SPELL_DELUSIONAL, SPELL_KLEPTOMANIA, SPELL_PARANOIA, SPELL_MANIC, SPELL_MARTYR_COMPLEX },
+ //CLASS_SHAMAN
+ { SPELL_MEGALOMANIA, SPELL_PARANOIA, SPELL_MANIC, SPELL_NARCISSISM, SPELL_MARTYR_COMPLEX, SPELL_DEMENTIA },
+ //CLASS_MAGE
+ { SPELL_MEGALOMANIA, SPELL_PARANOIA, SPELL_MANIC, SPELL_NARCISSISM, SPELL_MARTYR_COMPLEX, SPELL_DEMENTIA },
+ //CLASS_WARLOCK
+ { SPELL_MEGALOMANIA, SPELL_PARANOIA, SPELL_MANIC, SPELL_NARCISSISM, SPELL_MARTYR_COMPLEX, SPELL_DEMENTIA },
+ //CLASS_UNK
+ { },
+ //CLASS_DRUID
+ { SPELL_SOCIOPATH, SPELL_DELUSIONAL, SPELL_KLEPTOMANIA, SPELL_MEGALOMANIA, SPELL_PARANOIA, SPELL_MANIC, SPELL_NARCISSISM, SPELL_MARTYR_COMPLEX, SPELL_DEMENTIA }
+ };
+
+ PreventDefaultAction();
+ Unit* caster = eventInfo.GetActor();
+ uint32 spellId = Trinity::Containers::SelectRandomContainerElement(triggeredSpells[caster->getClass()]);
+ caster->CastSpell(caster, spellId, true, nullptr, aurEff);
+
+ if (roll_chance_i(10))
+ caster->Unit::Say(SAY_MADNESS);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_aura_of_madness_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_item_aura_of_madness::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
+ }
};
// 41404 - Dementia
-class spell_item_dementia : public SpellScriptLoader
+class spell_item_dementia : public AuraScript
{
- public:
- spell_item_dementia() : SpellScriptLoader("spell_item_dementia") { }
+ PrepareAuraScript(spell_item_dementia);
- class spell_item_dementia_AuraScript : public AuraScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareAuraScript(spell_item_dementia_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_DEMENTIA_POS,
- SPELL_DEMENTIA_NEG
- });
- }
-
- void HandlePeriodicDummy(AuraEffect const* aurEff)
- {
- PreventDefaultAction();
- GetTarget()->CastSpell(GetTarget(), RAND(SPELL_DEMENTIA_POS, SPELL_DEMENTIA_NEG), true, nullptr, aurEff);
- }
+ SPELL_DEMENTIA_POS,
+ SPELL_DEMENTIA_NEG
+ });
+ }
- void Register() override
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_item_dementia_AuraScript::HandlePeriodicDummy, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
- }
- };
+ void HandlePeriodicDummy(AuraEffect const* aurEff)
+ {
+ PreventDefaultAction();
+ GetTarget()->CastSpell(GetTarget(), RAND(SPELL_DEMENTIA_POS, SPELL_DEMENTIA_NEG), true, nullptr, aurEff);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_dementia_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_item_dementia::HandlePeriodicDummy, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
};
// 64411 - Blessing of Ancient Kings (Val'anyr, Hammer of Ancient Kings)
@@ -424,57 +369,46 @@ enum BlessingOfAncientKings
SPELL_PROTECTION_OF_ANCIENT_KINGS = 64413
};
-class spell_item_blessing_of_ancient_kings : public SpellScriptLoader
+class spell_item_blessing_of_ancient_kings : public AuraScript
{
- public:
- spell_item_blessing_of_ancient_kings() : SpellScriptLoader("spell_item_blessing_of_ancient_kings") { }
-
- class spell_item_blessing_of_ancient_kings_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_blessing_of_ancient_kings_AuraScript);
+ PrepareAuraScript(spell_item_blessing_of_ancient_kings);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_PROTECTION_OF_ANCIENT_KINGS });
- }
-
- bool CheckProc(ProcEventInfo& eventInfo)
- {
- return eventInfo.GetProcTarget() != nullptr;
- }
-
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
-
- HealInfo* healInfo = eventInfo.GetHealInfo();
- if (!healInfo || !healInfo->GetHeal())
- return;
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_PROTECTION_OF_ANCIENT_KINGS });
+ }
- int32 absorb = int32(CalculatePct(healInfo->GetHeal(), 15.0f));
- if (AuraEffect* protEff = eventInfo.GetProcTarget()->GetAuraEffect(SPELL_PROTECTION_OF_ANCIENT_KINGS, 0, eventInfo.GetActor()->GetGUID()))
- {
- // The shield can grow to a maximum size of 20,000 damage absorbtion
- protEff->SetAmount(std::min<int32>(protEff->GetAmount() + absorb, 20000));
+ bool CheckProc(ProcEventInfo& eventInfo)
+ {
+ return eventInfo.GetProcTarget() != nullptr;
+ }
- // Refresh and return to prevent replacing the aura
- protEff->GetBase()->RefreshDuration();
- }
- else
- GetTarget()->CastCustomSpell(SPELL_PROTECTION_OF_ANCIENT_KINGS, SPELLVALUE_BASE_POINT0, absorb, eventInfo.GetProcTarget(), true, nullptr, aurEff);
- }
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
- void Register() override
- {
- DoCheckProc += AuraCheckProcFn(spell_item_blessing_of_ancient_kings_AuraScript::CheckProc);
- OnEffectProc += AuraEffectProcFn(spell_item_blessing_of_ancient_kings_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
- }
- };
+ HealInfo* healInfo = eventInfo.GetHealInfo();
+ if (!healInfo || !healInfo->GetHeal())
+ return;
- AuraScript* GetAuraScript() const override
+ int32 absorb = int32(CalculatePct(healInfo->GetHeal(), 15.0f));
+ if (AuraEffect* protEff = eventInfo.GetProcTarget()->GetAuraEffect(SPELL_PROTECTION_OF_ANCIENT_KINGS, 0, eventInfo.GetActor()->GetGUID()))
{
- return new spell_item_blessing_of_ancient_kings_AuraScript();
+ // The shield can grow to a maximum size of 20,000 damage absorbtion
+ protEff->SetAmount(std::min<int32>(protEff->GetAmount() + absorb, 20000));
+
+ // Refresh and return to prevent replacing the aura
+ protEff->GetBase()->RefreshDuration();
}
+ else
+ GetTarget()->CastCustomSpell(SPELL_PROTECTION_OF_ANCIENT_KINGS, SPELLVALUE_BASE_POINT0, absorb, eventInfo.GetProcTarget(), true, nullptr, aurEff);
+ }
+
+ void Register() override
+ {
+ DoCheckProc += AuraCheckProcFn(spell_item_blessing_of_ancient_kings::CheckProc);
+ OnEffectProc += AuraEffectProcFn(spell_item_blessing_of_ancient_kings::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
+ }
};
enum DeadlyPrecision
@@ -483,64 +417,42 @@ enum DeadlyPrecision
};
// 71564 - Deadly Precision
-class spell_item_deadly_precision : public SpellScriptLoader
+class spell_item_deadly_precision : public AuraScript
{
- public:
- spell_item_deadly_precision() : SpellScriptLoader("spell_item_deadly_precision") { }
+ PrepareAuraScript(spell_item_deadly_precision);
- class spell_item_deadly_precision_charm_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_deadly_precision_charm_AuraScript);
-
- void HandleStackDrop(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/)
- {
- PreventDefaultAction();
- GetTarget()->RemoveAuraFromStack(GetId(), GetTarget()->GetGUID());
- }
-
- void Register() override
- {
- OnEffectProc += AuraEffectProcFn(spell_item_deadly_precision_charm_AuraScript::HandleStackDrop, EFFECT_0, SPELL_AURA_MOD_RATING);
- }
- };
+ void HandleStackDrop(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/)
+ {
+ PreventDefaultAction();
+ GetTarget()->RemoveAuraFromStack(GetId(), GetTarget()->GetGUID());
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_deadly_precision_charm_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_item_deadly_precision::HandleStackDrop, EFFECT_0, SPELL_AURA_MOD_RATING);
+ }
};
// 71563 - Deadly Precision Dummy
-class spell_item_deadly_precision_dummy : public SpellScriptLoader
+class spell_item_deadly_precision_dummy : public SpellScript
{
- public:
- spell_item_deadly_precision_dummy() : SpellScriptLoader("spell_item_deadly_precision_dummy") { }
-
- class spell_item_deadly_precision_dummy_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_deadly_precision_dummy_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_DEADLY_PRECISION });
- }
+ PrepareSpellScript(spell_item_deadly_precision_dummy);
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_DEADLY_PRECISION);
- GetCaster()->CastCustomSpell(spellInfo->Id, SPELLVALUE_AURA_STACK, spellInfo->StackAmount, GetCaster(), true);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_DEADLY_PRECISION });
+ }
- void Register() override
- {
- OnEffectHit += SpellEffectFn(spell_item_deadly_precision_dummy_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
- }
- };
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_DEADLY_PRECISION);
+ GetCaster()->CastCustomSpell(spellInfo->Id, SPELLVALUE_AURA_STACK, spellInfo->StackAmount, GetCaster(), true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_deadly_precision_dummy_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHit += SpellEffectFn(spell_item_deadly_precision_dummy::HandleDummy, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
+ }
};
enum DeathbringersWill
@@ -639,52 +551,41 @@ class spell_item_deathbringers_will : public SpellScriptLoader
};
// 47770 - Roll Dice
-class spell_item_decahedral_dwarven_dice : public SpellScriptLoader
+class spell_item_decahedral_dwarven_dice : public SpellScript
{
- public:
- spell_item_decahedral_dwarven_dice() : SpellScriptLoader("spell_item_decahedral_dwarven_dice") { }
-
- class spell_item_decahedral_dwarven_dice_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_decahedral_dwarven_dice_SpellScript);
+ PrepareSpellScript(spell_item_decahedral_dwarven_dice);
- enum
- {
- TEXT_DECAHEDRAL_DWARVEN_DICE = 26147
- };
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- if (!sObjectMgr->GetBroadcastText(TEXT_DECAHEDRAL_DWARVEN_DICE))
- return false;
- return true;
- }
+ enum
+ {
+ TEXT_DECAHEDRAL_DWARVEN_DICE = 26147
+ };
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sObjectMgr->GetBroadcastText(TEXT_DECAHEDRAL_DWARVEN_DICE))
+ return false;
+ return true;
+ }
- void HandleScript(SpellEffIndex /*effIndex*/)
- {
- GetCaster()->TextEmote(TEXT_DECAHEDRAL_DWARVEN_DICE, GetHitUnit());
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- static uint32 const minimum = 1;
- static uint32 const maximum = 100;
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->TextEmote(TEXT_DECAHEDRAL_DWARVEN_DICE, GetHitUnit());
- GetCaster()->ToPlayer()->DoRandomRoll(minimum, maximum);
- }
+ static uint32 const minimum = 1;
+ static uint32 const maximum = 100;
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_decahedral_dwarven_dice_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ GetCaster()->ToPlayer()->DoRandomRoll(minimum, maximum);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_decahedral_dwarven_dice_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_decahedral_dwarven_dice::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
// 8342 - Defibrillate (Goblin Jumper Cables) have 33% chance on success
@@ -749,36 +650,25 @@ enum DesperateDefense
};
// 33896 - Desperate Defense
-class spell_item_desperate_defense : public SpellScriptLoader
+class spell_item_desperate_defense : public AuraScript
{
- public:
- spell_item_desperate_defense() : SpellScriptLoader("spell_item_desperate_defense") { }
-
- class spell_item_desperate_defense_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_desperate_defense_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_DESPERATE_RAGE });
- }
+ PrepareAuraScript(spell_item_desperate_defense);
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
- {
- PreventDefaultAction();
- GetTarget()->CastSpell(GetTarget(), SPELL_DESPERATE_RAGE, true, nullptr, aurEff);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_DESPERATE_RAGE });
+ }
- void Register() override
- {
- OnEffectProc += AuraEffectProcFn(spell_item_desperate_defense_AuraScript::HandleProc, EFFECT_2, SPELL_AURA_PROC_TRIGGER_SPELL);
- }
- };
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
+ {
+ PreventDefaultAction();
+ GetTarget()->CastSpell(GetTarget(), SPELL_DESPERATE_RAGE, true, nullptr, aurEff);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_desperate_defense_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_item_desperate_defense::HandleProc, EFFECT_2, SPELL_AURA_PROC_TRIGGER_SPELL);
+ }
};
// http://www.wowhead.com/item=6522 Deviate Fish
@@ -792,42 +682,31 @@ enum DeviateFishSpells
SPELL_HEALTHY_SPIRIT = 8068,
};
-class spell_item_deviate_fish : public SpellScriptLoader
+class spell_item_deviate_fish : public SpellScript
{
- public:
- spell_item_deviate_fish() : SpellScriptLoader("spell_item_deviate_fish") { }
+ PrepareSpellScript(spell_item_deviate_fish);
- class spell_item_deviate_fish_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_deviate_fish_SpellScript);
-
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_SLEEPY, SPELL_INVIGORATE, SPELL_SHRINK, SPELL_PARTY_TIME, SPELL_HEALTHY_SPIRIT });
- }
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- Unit* caster = GetCaster();
- uint32 spellId = urand(SPELL_SLEEPY, SPELL_HEALTHY_SPIRIT);
- caster->CastSpell(caster, spellId, true, nullptr);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SLEEPY, SPELL_INVIGORATE, SPELL_SHRINK, SPELL_PARTY_TIME, SPELL_HEALTHY_SPIRIT });
+ }
- void Register() override
- {
- OnEffectHit += SpellEffectFn(spell_item_deviate_fish_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ uint32 spellId = urand(SPELL_SLEEPY, SPELL_HEALTHY_SPIRIT);
+ caster->CastSpell(caster, spellId, true, nullptr);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_deviate_fish_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHit += SpellEffectFn(spell_item_deviate_fish::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum DiscerningEyeBeastMisc
@@ -836,70 +715,48 @@ enum DiscerningEyeBeastMisc
};
// 59915 - Discerning Eye of the Beast Dummy
-class spell_item_discerning_eye_beast_dummy : public SpellScriptLoader
+class spell_item_discerning_eye_beast_dummy : public AuraScript
{
- public:
- spell_item_discerning_eye_beast_dummy() : SpellScriptLoader("spell_item_discerning_eye_beast_dummy") { }
-
- class spell_item_discerning_eye_beast_dummy_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_discerning_eye_beast_dummy_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_DISCERNING_EYE_BEAST });
- }
+ PrepareAuraScript(spell_item_discerning_eye_beast_dummy);
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_DISCERNING_EYE_BEAST, true, nullptr, aurEff);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_DISCERNING_EYE_BEAST });
+ }
- void Register() override
- {
- OnEffectProc += AuraEffectProcFn(spell_item_discerning_eye_beast_dummy_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
- }
- };
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+ eventInfo.GetActor()->CastSpell(nullptr, SPELL_DISCERNING_EYE_BEAST, true, nullptr, aurEff);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_discerning_eye_beast_dummy_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_item_discerning_eye_beast_dummy::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
+ }
};
// 71610, 71641 - Echoes of Light (Althor's Abacus)
-class spell_item_echoes_of_light : public SpellScriptLoader
+class spell_item_echoes_of_light : public SpellScript
{
- public:
- spell_item_echoes_of_light() : SpellScriptLoader("spell_item_echoes_of_light") { }
-
- class spell_item_echoes_of_light_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_echoes_of_light_SpellScript);
-
- void FilterTargets(std::list<WorldObject*>& targets)
- {
- if (targets.size() < 2)
- return;
+ PrepareSpellScript(spell_item_echoes_of_light);
- targets.sort(Trinity::HealthPctOrderPred());
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ if (targets.size() < 2)
+ return;
- WorldObject* target = targets.front();
- targets.clear();
- targets.push_back(target);
- }
+ targets.sort(Trinity::HealthPctOrderPred());
- void Register() override
- {
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_item_echoes_of_light_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY);
- }
- };
+ WorldObject* target = targets.front();
+ targets.clear();
+ targets.push_back(target);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_echoes_of_light_SpellScript();
- }
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_item_echoes_of_light::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY);
+ }
};
// 7434 - Fate Rune of Unsurpassed Vigor
@@ -908,36 +765,25 @@ enum FateRuneOfUnsurpassedVigor
SPELL_UNSURPASSED_VIGOR = 25733
};
-class spell_item_fate_rune_of_unsurpassed_vigor : public SpellScriptLoader
+class spell_item_fate_rune_of_unsurpassed_vigor : public AuraScript
{
- public:
- spell_item_fate_rune_of_unsurpassed_vigor() : SpellScriptLoader("spell_item_fate_rune_of_unsurpassed_vigor") { }
-
- class spell_item_fate_rune_of_unsurpassed_vigor_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_fate_rune_of_unsurpassed_vigor_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_UNSURPASSED_VIGOR });
- }
+ PrepareAuraScript(spell_item_fate_rune_of_unsurpassed_vigor);
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/)
- {
- PreventDefaultAction();
- GetTarget()->CastSpell(GetTarget(), SPELL_UNSURPASSED_VIGOR, true);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_UNSURPASSED_VIGOR });
+ }
- void Register() override
- {
- OnEffectProc += AuraEffectProcFn(spell_item_fate_rune_of_unsurpassed_vigor_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
- }
- };
+ void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/)
+ {
+ PreventDefaultAction();
+ GetTarget()->CastSpell(GetTarget(), SPELL_UNSURPASSED_VIGOR, true);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_fate_rune_of_unsurpassed_vigor_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_item_fate_rune_of_unsurpassed_vigor::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
+ }
};
// http://www.wowhead.com/item=47499 Flask of the North
@@ -949,63 +795,52 @@ enum FlaskOfTheNorthSpells
SPELL_FLASK_OF_THE_NORTH_STR = 67018,
};
-class spell_item_flask_of_the_north : public SpellScriptLoader
+class spell_item_flask_of_the_north : public SpellScript
{
- public:
- spell_item_flask_of_the_north() : SpellScriptLoader("spell_item_flask_of_the_north") { }
-
- class spell_item_flask_of_the_north_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_flask_of_the_north_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_FLASK_OF_THE_NORTH_SP, SPELL_FLASK_OF_THE_NORTH_AP, SPELL_FLASK_OF_THE_NORTH_STR });
- }
-
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- Unit* caster = GetCaster();
- std::vector<uint32> possibleSpells;
- switch (caster->getClass())
- {
- case CLASS_WARLOCK:
- case CLASS_MAGE:
- case CLASS_PRIEST:
- possibleSpells.push_back(SPELL_FLASK_OF_THE_NORTH_SP);
- break;
- case CLASS_DEATH_KNIGHT:
- case CLASS_WARRIOR:
- possibleSpells.push_back(SPELL_FLASK_OF_THE_NORTH_STR);
- break;
- case CLASS_ROGUE:
- case CLASS_HUNTER:
- possibleSpells.push_back(SPELL_FLASK_OF_THE_NORTH_AP);
- break;
- case CLASS_DRUID:
- case CLASS_PALADIN:
- possibleSpells.push_back(SPELL_FLASK_OF_THE_NORTH_SP);
- possibleSpells.push_back(SPELL_FLASK_OF_THE_NORTH_STR);
- break;
- case CLASS_SHAMAN:
- possibleSpells.push_back(SPELL_FLASK_OF_THE_NORTH_SP);
- possibleSpells.push_back(SPELL_FLASK_OF_THE_NORTH_AP);
- break;
- }
+ PrepareSpellScript(spell_item_flask_of_the_north);
- caster->CastSpell(caster, possibleSpells[urand(0, (possibleSpells.size() - 1))], true, nullptr);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_FLASK_OF_THE_NORTH_SP, SPELL_FLASK_OF_THE_NORTH_AP, SPELL_FLASK_OF_THE_NORTH_STR });
+ }
- void Register() override
- {
- OnEffectHit += SpellEffectFn(spell_item_flask_of_the_north_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ std::vector<uint32> possibleSpells;
+ switch (caster->getClass())
+ {
+ case CLASS_WARLOCK:
+ case CLASS_MAGE:
+ case CLASS_PRIEST:
+ possibleSpells.push_back(SPELL_FLASK_OF_THE_NORTH_SP);
+ break;
+ case CLASS_DEATH_KNIGHT:
+ case CLASS_WARRIOR:
+ possibleSpells.push_back(SPELL_FLASK_OF_THE_NORTH_STR);
+ break;
+ case CLASS_ROGUE:
+ case CLASS_HUNTER:
+ possibleSpells.push_back(SPELL_FLASK_OF_THE_NORTH_AP);
+ break;
+ case CLASS_DRUID:
+ case CLASS_PALADIN:
+ possibleSpells.push_back(SPELL_FLASK_OF_THE_NORTH_SP);
+ possibleSpells.push_back(SPELL_FLASK_OF_THE_NORTH_STR);
+ break;
+ case CLASS_SHAMAN:
+ possibleSpells.push_back(SPELL_FLASK_OF_THE_NORTH_SP);
+ possibleSpells.push_back(SPELL_FLASK_OF_THE_NORTH_AP);
+ break;
+ }
+
+ caster->CastSpell(caster, possibleSpells[urand(0, (possibleSpells.size() - 1))], true, nullptr);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_flask_of_the_north_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHit += SpellEffectFn(spell_item_flask_of_the_north::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum FrozenShadoweave
@@ -1015,42 +850,31 @@ enum FrozenShadoweave
// 39372 - Frozen Shadoweave
// Frozen Shadoweave set 3p bonus
-class spell_item_frozen_shadoweave : public SpellScriptLoader
+class spell_item_frozen_shadoweave : public AuraScript
{
- public:
- spell_item_frozen_shadoweave() : SpellScriptLoader("spell_item_frozen_shadoweave") { }
-
- class spell_item_frozen_shadoweave_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_frozen_shadoweave_AuraScript);
+ PrepareAuraScript(spell_item_frozen_shadoweave);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_SHADOWMEND });
- }
-
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
- DamageInfo* damageInfo = eventInfo.GetDamageInfo();
- if (!damageInfo || !damageInfo->GetDamage())
- return;
-
- int32 amount = CalculatePct(static_cast<int32>(damageInfo->GetDamage()), aurEff->GetAmount());
- Unit* caster = eventInfo.GetActor();
- caster->CastCustomSpell(SPELL_SHADOWMEND, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SHADOWMEND });
+ }
- void Register() override
- {
- OnEffectProc += AuraEffectProcFn(spell_item_frozen_shadoweave_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
- }
- };
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+ DamageInfo* damageInfo = eventInfo.GetDamageInfo();
+ if (!damageInfo || !damageInfo->GetDamage())
+ return;
+
+ int32 amount = CalculatePct(static_cast<int32>(damageInfo->GetDamage()), aurEff->GetAmount());
+ Unit* caster = eventInfo.GetActor();
+ caster->CastCustomSpell(SPELL_SHADOWMEND, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_frozen_shadoweave_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_item_frozen_shadoweave::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
+ }
};
// http://www.wowhead.com/item=10645 Gnomish Death Ray
@@ -1061,42 +885,31 @@ enum GnomishDeathRay
SPELL_GNOMISH_DEATH_RAY_TARGET = 13279,
};
-class spell_item_gnomish_death_ray : public SpellScriptLoader
+class spell_item_gnomish_death_ray : public SpellScript
{
- public:
- spell_item_gnomish_death_ray() : SpellScriptLoader("spell_item_gnomish_death_ray") { }
-
- class spell_item_gnomish_death_ray_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_gnomish_death_ray_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_GNOMISH_DEATH_RAY_SELF, SPELL_GNOMISH_DEATH_RAY_TARGET });
- }
-
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- Unit* caster = GetCaster();
- if (Unit* target = GetHitUnit())
- {
- if (urand(0, 99) < 15)
- caster->CastSpell(caster, SPELL_GNOMISH_DEATH_RAY_SELF, true); // failure
- else
- caster->CastSpell(target, SPELL_GNOMISH_DEATH_RAY_TARGET, true);
- }
- }
+ PrepareSpellScript(spell_item_gnomish_death_ray);
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_gnomish_death_ray_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_GNOMISH_DEATH_RAY_SELF, SPELL_GNOMISH_DEATH_RAY_TARGET });
+ }
- SpellScript* GetSpellScript() const override
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ if (Unit* target = GetHitUnit())
{
- return new spell_item_gnomish_death_ray_SpellScript();
+ if (urand(0, 99) < 15)
+ caster->CastSpell(caster, SPELL_GNOMISH_DEATH_RAY_SELF, true); // failure
+ else
+ caster->CastSpell(target, SPELL_GNOMISH_DEATH_RAY_TARGET, true);
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_gnomish_death_ray::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
// Item 10721: Gnomish Harm Prevention Belt
@@ -1106,35 +919,24 @@ enum HarmPreventionBelt
SPELL_FORCEFIELD_COLLAPSE = 13235
};
-class spell_item_harm_prevention_belt : public SpellScriptLoader
+class spell_item_harm_prevention_belt : public AuraScript
{
- public:
- spell_item_harm_prevention_belt() : SpellScriptLoader("spell_item_harm_prevention_belt") { }
-
- class spell_item_harm_prevention_belt_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_harm_prevention_belt_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_FORCEFIELD_COLLAPSE });
- }
+ PrepareAuraScript(spell_item_harm_prevention_belt);
- void HandleProc(ProcEventInfo& /*eventInfo*/)
- {
- GetTarget()->CastSpell((Unit*)nullptr, SPELL_FORCEFIELD_COLLAPSE, true);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_FORCEFIELD_COLLAPSE });
+ }
- void Register() override
- {
- OnProc += AuraProcFn(spell_item_harm_prevention_belt_AuraScript::HandleProc);
- }
- };
+ void HandleProc(ProcEventInfo& /*eventInfo*/)
+ {
+ GetTarget()->CastSpell(nullptr, SPELL_FORCEFIELD_COLLAPSE, true);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_harm_prevention_belt_AuraScript();
- }
+ void Register() override
+ {
+ OnProc += AuraProcFn(spell_item_harm_prevention_belt::HandleProc);
+ }
};
// Item 23004 - Idol of Longevity
@@ -1144,36 +946,25 @@ enum IdolOfLongevity
SPELL_HEALING_TOUCH_MANA = 28848
};
-class spell_item_healing_touch_refund : public SpellScriptLoader
+class spell_item_healing_touch_refund : public AuraScript
{
- public:
- spell_item_healing_touch_refund() : SpellScriptLoader("spell_item_healing_touch_refund") { }
-
- class spell_item_healing_touch_refund_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_healing_touch_refund_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_HEALING_TOUCH_MANA });
- }
+ PrepareAuraScript(spell_item_healing_touch_refund);
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_HEALING_TOUCH_MANA, true, nullptr, aurEff);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_HEALING_TOUCH_MANA });
+ }
- void Register() override
- {
- OnEffectProc += AuraEffectProcFn(spell_item_healing_touch_refund_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
- }
- };
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+ eventInfo.GetActor()->CastSpell(nullptr, SPELL_HEALING_TOUCH_MANA, true, nullptr, aurEff);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_healing_touch_refund_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_item_healing_touch_refund::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
+ }
};
enum Heartpierce
@@ -1241,7 +1032,7 @@ class spell_item_heartpierce : public SpellScriptLoader
return;
}
- caster->CastSpell((Unit*)nullptr, spellId, true, nullptr, aurEff);
+ caster->CastSpell(nullptr, spellId, true, nullptr, aurEff);
}
void Register() override
@@ -1257,36 +1048,25 @@ class spell_item_heartpierce : public SpellScriptLoader
};
// 40971 - Bonus Healing (Crystal Spire of Karabor)
-class spell_item_crystal_spire_of_karabor : public SpellScriptLoader
+class spell_item_crystal_spire_of_karabor : public AuraScript
{
- public:
- spell_item_crystal_spire_of_karabor() : SpellScriptLoader("spell_item_crystal_spire_of_karabor") { }
-
- class spell_item_crystal_spire_of_karabor_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_crystal_spire_of_karabor_AuraScript);
-
- bool CheckProc(ProcEventInfo& eventInfo)
- {
- int32 pct = GetSpellInfo()->Effects[EFFECT_0].BasePoints;
- if (HealInfo* healInfo = eventInfo.GetHealInfo())
- if (Unit* healTarget = healInfo->GetTarget())
- if (healTarget->GetHealth() - healInfo->GetEffectiveHeal() <= healTarget->CountPctFromMaxHealth(pct))
- return true;
+ PrepareAuraScript(spell_item_crystal_spire_of_karabor);
- return false;
- }
+ bool CheckProc(ProcEventInfo& eventInfo)
+ {
+ int32 pct = GetSpellInfo()->Effects[EFFECT_0].BasePoints;
+ if (HealInfo* healInfo = eventInfo.GetHealInfo())
+ if (Unit* healTarget = healInfo->GetTarget())
+ if (healTarget->GetHealth() - healInfo->GetEffectiveHeal() <= healTarget->CountPctFromMaxHealth(pct))
+ return true;
- void Register() override
- {
- DoCheckProc += AuraCheckProcFn(spell_item_crystal_spire_of_karabor_AuraScript::CheckProc);
- }
- };
+ return false;
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_crystal_spire_of_karabor_AuraScript();
- }
+ void Register() override
+ {
+ DoCheckProc += AuraCheckProcFn(spell_item_crystal_spire_of_karabor::CheckProc);
+ }
};
// http://www.wowhead.com/item=27388 Mr. Pinchy
@@ -1300,56 +1080,45 @@ enum MakeAWish
SPELL_MR_PINCHYS_GIFT = 33064,
};
-class spell_item_make_a_wish : public SpellScriptLoader
+class spell_item_make_a_wish : public SpellScript
{
- public:
- spell_item_make_a_wish() : SpellScriptLoader("spell_item_make_a_wish") { }
+ PrepareSpellScript(spell_item_make_a_wish);
- class spell_item_make_a_wish_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_make_a_wish_SpellScript);
-
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_MR_PINCHYS_BLESSING,
- SPELL_SUMMON_MIGHTY_MR_PINCHY,
- SPELL_SUMMON_FURIOUS_MR_PINCHY,
- SPELL_TINY_MAGICAL_CRAWDAD,
- SPELL_MR_PINCHYS_GIFT
- });
- }
-
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- Unit* caster = GetCaster();
- uint32 spellId = SPELL_MR_PINCHYS_GIFT;
- switch (urand(1, 5))
- {
- case 1: spellId = SPELL_MR_PINCHYS_BLESSING; break;
- case 2: spellId = SPELL_SUMMON_MIGHTY_MR_PINCHY; break;
- case 3: spellId = SPELL_SUMMON_FURIOUS_MR_PINCHY; break;
- case 4: spellId = SPELL_TINY_MAGICAL_CRAWDAD; break;
- }
- caster->CastSpell(caster, spellId, true, nullptr);
- }
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- void Register() override
- {
- OnEffectHit += SpellEffectFn(spell_item_make_a_wish_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
+ {
+ SPELL_MR_PINCHYS_BLESSING,
+ SPELL_SUMMON_MIGHTY_MR_PINCHY,
+ SPELL_SUMMON_FURIOUS_MR_PINCHY,
+ SPELL_TINY_MAGICAL_CRAWDAD,
+ SPELL_MR_PINCHYS_GIFT
+ });
+ }
- SpellScript* GetSpellScript() const override
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ uint32 spellId = SPELL_MR_PINCHYS_GIFT;
+ switch (urand(1, 5))
{
- return new spell_item_make_a_wish_SpellScript();
+ case 1: spellId = SPELL_MR_PINCHYS_BLESSING; break;
+ case 2: spellId = SPELL_SUMMON_MIGHTY_MR_PINCHY; break;
+ case 3: spellId = SPELL_SUMMON_FURIOUS_MR_PINCHY; break;
+ case 4: spellId = SPELL_TINY_MAGICAL_CRAWDAD; break;
}
+ caster->CastSpell(caster, spellId, true, nullptr);
+ }
+
+ void Register() override
+ {
+ OnEffectHit += SpellEffectFn(spell_item_make_a_wish::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum MarkOfConquest
@@ -1360,97 +1129,75 @@ enum MarkOfConquest
// Item - 27920: Mark of Conquest
// Item - 27921: Mark of Conquest
// 33510 - Health Restore
-class spell_item_mark_of_conquest : public SpellScriptLoader
+class spell_item_mark_of_conquest : public AuraScript
{
- public:
- spell_item_mark_of_conquest() : SpellScriptLoader("spell_item_mark_of_conquest") { }
-
- class spell_item_mark_of_conquest_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_mark_of_conquest_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_MARK_OF_CONQUEST_ENERGIZE });
- }
+ PrepareAuraScript(spell_item_mark_of_conquest);
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- if (eventInfo.GetTypeMask() & (PROC_FLAG_DONE_RANGED_AUTO_ATTACK | PROC_FLAG_DONE_SPELL_RANGED_DMG_CLASS))
- {
- // in that case, do not cast heal spell
- PreventDefaultAction();
- // but mana instead
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_MARK_OF_CONQUEST_ENERGIZE, true, nullptr, aurEff);
- }
- }
-
- void Register() override
- {
- OnEffectProc += AuraEffectProcFn(spell_item_mark_of_conquest_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
- }
- };
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_MARK_OF_CONQUEST_ENERGIZE });
+ }
- AuraScript* GetAuraScript() const override
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ if (eventInfo.GetTypeMask() & (PROC_FLAG_DONE_RANGED_AUTO_ATTACK | PROC_FLAG_DONE_SPELL_RANGED_DMG_CLASS))
{
- return new spell_item_mark_of_conquest_AuraScript();
+ // in that case, do not cast heal spell
+ PreventDefaultAction();
+ // but mana instead
+ eventInfo.GetActor()->CastSpell(nullptr, SPELL_MARK_OF_CONQUEST_ENERGIZE, true, nullptr, aurEff);
}
+ }
+
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_item_mark_of_conquest::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
+ }
};
// http://www.wowhead.com/item=32686 Mingo's Fortune Giblets
// 40802 Mingo's Fortune Generator
-class spell_item_mingos_fortune_generator : public SpellScriptLoader
+class spell_item_mingos_fortune_generator : public SpellScript
{
- public:
- spell_item_mingos_fortune_generator() : SpellScriptLoader("spell_item_mingos_fortune_generator") { }
-
- class spell_item_mingos_fortune_generator_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_mingos_fortune_generator_SpellScript);
-
- void HandleDummy(SpellEffIndex effIndex)
- {
- // Selecting one from Bloodstained Fortune item
- uint32 newitemid;
- switch (urand(1, 20))
- {
- case 1: newitemid = 32688; break;
- case 2: newitemid = 32689; break;
- case 3: newitemid = 32690; break;
- case 4: newitemid = 32691; break;
- case 5: newitemid = 32692; break;
- case 6: newitemid = 32693; break;
- case 7: newitemid = 32700; break;
- case 8: newitemid = 32701; break;
- case 9: newitemid = 32702; break;
- case 10: newitemid = 32703; break;
- case 11: newitemid = 32704; break;
- case 12: newitemid = 32705; break;
- case 13: newitemid = 32706; break;
- case 14: newitemid = 32707; break;
- case 15: newitemid = 32708; break;
- case 16: newitemid = 32709; break;
- case 17: newitemid = 32710; break;
- case 18: newitemid = 32711; break;
- case 19: newitemid = 32712; break;
- case 20: newitemid = 32713; break;
- default:
- return;
- }
+ PrepareSpellScript(spell_item_mingos_fortune_generator);
- CreateItem(effIndex, newitemid);
- }
+ void HandleDummy(SpellEffIndex effIndex)
+ {
+ // Selecting one from Bloodstained Fortune item
+ uint32 newitemid;
+ switch (urand(1, 20))
+ {
+ case 1: newitemid = 32688; break;
+ case 2: newitemid = 32689; break;
+ case 3: newitemid = 32690; break;
+ case 4: newitemid = 32691; break;
+ case 5: newitemid = 32692; break;
+ case 6: newitemid = 32693; break;
+ case 7: newitemid = 32700; break;
+ case 8: newitemid = 32701; break;
+ case 9: newitemid = 32702; break;
+ case 10: newitemid = 32703; break;
+ case 11: newitemid = 32704; break;
+ case 12: newitemid = 32705; break;
+ case 13: newitemid = 32706; break;
+ case 14: newitemid = 32707; break;
+ case 15: newitemid = 32708; break;
+ case 16: newitemid = 32709; break;
+ case 17: newitemid = 32710; break;
+ case 18: newitemid = 32711; break;
+ case 19: newitemid = 32712; break;
+ case 20: newitemid = 32713; break;
+ default:
+ return;
+ }
- void Register() override
- {
- OnEffectHit += SpellEffectFn(spell_item_mingos_fortune_generator_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ CreateItem(effIndex, newitemid);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_mingos_fortune_generator_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHit += SpellEffectFn(spell_item_mingos_fortune_generator::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
// 71875, 71877 - Item - Black Bruise: Necrotic Touch Proc
@@ -1459,47 +1206,36 @@ enum NecroticTouch
SPELL_ITEM_NECROTIC_TOUCH_PROC = 71879
};
-class spell_item_necrotic_touch : public SpellScriptLoader
+class spell_item_necrotic_touch : public AuraScript
{
- public:
- spell_item_necrotic_touch() : SpellScriptLoader("spell_item_necrotic_touch") { }
-
- class spell_item_necrotic_touch_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_necrotic_touch_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_ITEM_NECROTIC_TOUCH_PROC });
- }
+ PrepareAuraScript(spell_item_necrotic_touch);
- bool CheckProc(ProcEventInfo& eventInfo)
- {
- return eventInfo.GetProcTarget() && eventInfo.GetProcTarget()->IsAlive();
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_ITEM_NECROTIC_TOUCH_PROC });
+ }
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
- DamageInfo* damageInfo = eventInfo.GetDamageInfo();
- if (!damageInfo || !damageInfo->GetDamage())
- return;
+ bool CheckProc(ProcEventInfo& eventInfo)
+ {
+ return eventInfo.GetProcTarget() && eventInfo.GetProcTarget()->IsAlive();
+ }
- int32 bp = CalculatePct(static_cast<int32>(damageInfo->GetDamage()), aurEff->GetAmount());
- GetTarget()->CastCustomSpell(SPELL_ITEM_NECROTIC_TOUCH_PROC, SPELLVALUE_BASE_POINT0, bp, eventInfo.GetProcTarget(), true, nullptr, aurEff);
- }
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+ DamageInfo* damageInfo = eventInfo.GetDamageInfo();
+ if (!damageInfo || !damageInfo->GetDamage())
+ return;
- void Register() override
- {
- DoCheckProc += AuraCheckProcFn(spell_item_necrotic_touch_AuraScript::CheckProc);
- OnEffectProc += AuraEffectProcFn(spell_item_necrotic_touch_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
- }
- };
+ int32 bp = CalculatePct(static_cast<int32>(damageInfo->GetDamage()), aurEff->GetAmount());
+ GetTarget()->CastCustomSpell(SPELL_ITEM_NECROTIC_TOUCH_PROC, SPELLVALUE_BASE_POINT0, bp, eventInfo.GetProcTarget(), true, nullptr, aurEff);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_necrotic_touch_AuraScript();
- }
+ void Register() override
+ {
+ DoCheckProc += AuraCheckProcFn(spell_item_necrotic_touch::CheckProc);
+ OnEffectProc += AuraEffectProcFn(spell_item_necrotic_touch::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
+ }
};
// http://www.wowhead.com/item=10720 Gnomish Net-o-Matic Projector
@@ -1511,50 +1247,39 @@ enum NetOMaticSpells
SPELL_NET_O_MATIC_TRIGGERED3 = 13099,
};
-class spell_item_net_o_matic : public SpellScriptLoader
+class spell_item_net_o_matic : public SpellScript
{
- public:
- spell_item_net_o_matic() : SpellScriptLoader("spell_item_net_o_matic") { }
+ PrepareSpellScript(spell_item_net_o_matic);
- class spell_item_net_o_matic_SpellScript : public SpellScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareSpellScript(spell_item_net_o_matic_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_NET_O_MATIC_TRIGGERED1,
- SPELL_NET_O_MATIC_TRIGGERED2,
- SPELL_NET_O_MATIC_TRIGGERED3
- });
- }
-
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- if (Unit* target = GetHitUnit())
- {
- uint32 spellId = SPELL_NET_O_MATIC_TRIGGERED3;
- uint32 roll = urand(0, 99);
- if (roll < 2) // 2% for 30 sec self root (off-like chance unknown)
- spellId = SPELL_NET_O_MATIC_TRIGGERED1;
- else if (roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
- spellId = SPELL_NET_O_MATIC_TRIGGERED2;
-
- GetCaster()->CastSpell(target, spellId, true, nullptr);
- }
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_net_o_matic_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ SPELL_NET_O_MATIC_TRIGGERED1,
+ SPELL_NET_O_MATIC_TRIGGERED2,
+ SPELL_NET_O_MATIC_TRIGGERED3
+ });
+ }
- SpellScript* GetSpellScript() const override
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
{
- return new spell_item_net_o_matic_SpellScript();
+ uint32 spellId = SPELL_NET_O_MATIC_TRIGGERED3;
+ uint32 roll = urand(0, 99);
+ if (roll < 2) // 2% for 30 sec self root (off-like chance unknown)
+ spellId = SPELL_NET_O_MATIC_TRIGGERED1;
+ else if (roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
+ spellId = SPELL_NET_O_MATIC_TRIGGERED2;
+
+ GetCaster()->CastSpell(target, spellId, true, nullptr);
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_net_o_matic::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
// http://www.wowhead.com/item=8529 Noggenfogger Elixir
@@ -1566,83 +1291,61 @@ enum NoggenfoggerElixirSpells
SPELL_NOGGENFOGGER_ELIXIR_TRIGGERED3 = 16591,
};
-class spell_item_noggenfogger_elixir : public SpellScriptLoader
+class spell_item_noggenfogger_elixir : public SpellScript
{
- public:
- spell_item_noggenfogger_elixir() : SpellScriptLoader("spell_item_noggenfogger_elixir") { }
-
- class spell_item_noggenfogger_elixir_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_noggenfogger_elixir_SpellScript);
-
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
+ PrepareSpellScript(spell_item_noggenfogger_elixir);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_NOGGENFOGGER_ELIXIR_TRIGGERED1,
- SPELL_NOGGENFOGGER_ELIXIR_TRIGGERED2,
- SPELL_NOGGENFOGGER_ELIXIR_TRIGGERED3
- });
- }
-
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- Unit* caster = GetCaster();
- uint32 spellId = SPELL_NOGGENFOGGER_ELIXIR_TRIGGERED3;
- switch (urand(1, 3))
- {
- case 1: spellId = SPELL_NOGGENFOGGER_ELIXIR_TRIGGERED1; break;
- case 2: spellId = SPELL_NOGGENFOGGER_ELIXIR_TRIGGERED2; break;
- }
-
- caster->CastSpell(caster, spellId, true, nullptr);
- }
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- void Register() override
- {
- OnEffectHit += SpellEffectFn(spell_item_noggenfogger_elixir_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
+ {
+ SPELL_NOGGENFOGGER_ELIXIR_TRIGGERED1,
+ SPELL_NOGGENFOGGER_ELIXIR_TRIGGERED2,
+ SPELL_NOGGENFOGGER_ELIXIR_TRIGGERED3
+ });
+ }
- SpellScript* GetSpellScript() const override
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ uint32 spellId = SPELL_NOGGENFOGGER_ELIXIR_TRIGGERED3;
+ switch (urand(1, 3))
{
- return new spell_item_noggenfogger_elixir_SpellScript();
+ case 1: spellId = SPELL_NOGGENFOGGER_ELIXIR_TRIGGERED1; break;
+ case 2: spellId = SPELL_NOGGENFOGGER_ELIXIR_TRIGGERED2; break;
}
+
+ caster->CastSpell(caster, spellId, true, nullptr);
+ }
+
+ void Register() override
+ {
+ OnEffectHit += SpellEffectFn(spell_item_noggenfogger_elixir::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
// 29601 - Enlightenment (Pendant of the Violet Eye)
-class spell_item_pendant_of_the_violet_eye : public SpellScriptLoader
+class spell_item_pendant_of_the_violet_eye : public AuraScript
{
- public:
- spell_item_pendant_of_the_violet_eye() : SpellScriptLoader("spell_item_pendant_of_the_violet_eye") { }
-
- class spell_item_pendant_of_the_violet_eye_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_pendant_of_the_violet_eye_AuraScript);
-
- bool CheckProc(ProcEventInfo& eventInfo)
- {
- if (SpellInfo const* spellInfo = eventInfo.GetSpellInfo())
- return spellInfo->PowerType == POWER_MANA || (spellInfo->ManaCost != 0 && spellInfo->ManaCostPercentage != 0 && spellInfo->ManaCostPerlevel != 0);
+ PrepareAuraScript(spell_item_pendant_of_the_violet_eye);
- return false;
- }
+ bool CheckProc(ProcEventInfo& eventInfo)
+ {
+ if (SpellInfo const* spellInfo = eventInfo.GetSpellInfo())
+ return spellInfo->PowerType == POWER_MANA || (spellInfo->ManaCost != 0 && spellInfo->ManaCostPercentage != 0 && spellInfo->ManaCostPerlevel != 0);
- void Register() override
- {
- DoCheckProc += AuraCheckProcFn(spell_item_pendant_of_the_violet_eye_AuraScript::CheckProc);
- }
- };
+ return false;
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_pendant_of_the_violet_eye_AuraScript();
- }
+ void Register() override
+ {
+ DoCheckProc += AuraCheckProcFn(spell_item_pendant_of_the_violet_eye::CheckProc);
+ }
};
enum PersistentShieldMisc
@@ -1651,50 +1354,39 @@ enum PersistentShieldMisc
};
// 26467 - Persistent Shield
-class spell_item_persistent_shield : public SpellScriptLoader
+class spell_item_persistent_shield : public AuraScript
{
- public:
- spell_item_persistent_shield() : SpellScriptLoader("spell_item_persistent_shield") { }
-
- class spell_item_persistent_shield_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_persistent_shield_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_PERSISTENT_SHIELD_TRIGGERED });
- }
+ PrepareAuraScript(spell_item_persistent_shield);
- bool CheckProc(ProcEventInfo& eventInfo)
- {
- return eventInfo.GetHealInfo() && eventInfo.GetHealInfo()->GetHeal();
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_PERSISTENT_SHIELD_TRIGGERED });
+ }
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- Unit* caster = eventInfo.GetActor();
- Unit* target = eventInfo.GetProcTarget();
- int32 bp0 = CalculatePct(eventInfo.GetHealInfo()->GetHeal(), 15);
+ bool CheckProc(ProcEventInfo& eventInfo)
+ {
+ return eventInfo.GetHealInfo() && eventInfo.GetHealInfo()->GetHeal();
+ }
- // Scarab Brooch does not replace stronger shields
- if (AuraEffect const* shield = target->GetAuraEffect(SPELL_PERSISTENT_SHIELD_TRIGGERED, EFFECT_0, caster->GetGUID()))
- if (shield->GetAmount() > bp0)
- return;
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ Unit* caster = eventInfo.GetActor();
+ Unit* target = eventInfo.GetProcTarget();
+ int32 bp0 = CalculatePct(eventInfo.GetHealInfo()->GetHeal(), 15);
- caster->CastCustomSpell(SPELL_PERSISTENT_SHIELD_TRIGGERED, SPELLVALUE_BASE_POINT0, bp0, target, true, nullptr, aurEff);
- }
+ // Scarab Brooch does not replace stronger shields
+ if (AuraEffect const* shield = target->GetAuraEffect(SPELL_PERSISTENT_SHIELD_TRIGGERED, EFFECT_0, caster->GetGUID()))
+ if (shield->GetAmount() > bp0)
+ return;
- void Register() override
- {
- DoCheckProc += AuraCheckProcFn(spell_item_persistent_shield_AuraScript::CheckProc);
- OnEffectProc += AuraEffectProcFn(spell_item_persistent_shield_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
- }
- };
+ caster->CastCustomSpell(SPELL_PERSISTENT_SHIELD_TRIGGERED, SPELLVALUE_BASE_POINT0, bp0, target, true, nullptr, aurEff);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_persistent_shield_AuraScript();
- }
+ void Register() override
+ {
+ DoCheckProc += AuraCheckProcFn(spell_item_persistent_shield::CheckProc);
+ OnEffectProc += AuraEffectProcFn(spell_item_persistent_shield::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
+ }
};
enum PetHealing
@@ -1705,71 +1397,49 @@ enum PetHealing
// 37381 - Pet Healing
// Hunter T5 2P Bonus
// Warlock T5 2P Bonus
-class spell_item_pet_healing : public SpellScriptLoader
+class spell_item_pet_healing : public AuraScript
{
- public:
- spell_item_pet_healing() : SpellScriptLoader("spell_item_pet_healing") { }
-
- class spell_item_pet_healing_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_pet_healing_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_HEALTH_LINK });
- }
-
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
- DamageInfo* damageInfo = eventInfo.GetDamageInfo();
- if (!damageInfo || !damageInfo->GetDamage())
- return;
+ PrepareAuraScript(spell_item_pet_healing);
- int32 bp = CalculatePct(static_cast<int32>(damageInfo->GetDamage()), aurEff->GetAmount());
- Unit* caster = eventInfo.GetActor();
- caster->CastCustomSpell(SPELL_HEALTH_LINK, SPELLVALUE_BASE_POINT0, bp, (Unit*)nullptr, true, nullptr, aurEff);
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_HEALTH_LINK });
+ }
- void Register() override
- {
- OnEffectProc += AuraEffectProcFn(spell_item_pet_healing_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
- }
- };
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+ DamageInfo* damageInfo = eventInfo.GetDamageInfo();
+ if (!damageInfo || !damageInfo->GetDamage())
+ return;
+
+ int32 bp = CalculatePct(static_cast<int32>(damageInfo->GetDamage()), aurEff->GetAmount());
+ Unit* caster = eventInfo.GetActor();
+ caster->CastCustomSpell(SPELL_HEALTH_LINK, SPELLVALUE_BASE_POINT0, bp, (Unit*)nullptr, true, nullptr, aurEff);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_pet_healing_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_item_pet_healing::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
+ }
};
// 17512 - Piccolo of the Flaming Fire
-class spell_item_piccolo_of_the_flaming_fire : public SpellScriptLoader
+class spell_item_piccolo_of_the_flaming_fire : public SpellScript
{
- public:
- spell_item_piccolo_of_the_flaming_fire() : SpellScriptLoader("spell_item_piccolo_of_the_flaming_fire") { }
-
- class spell_item_piccolo_of_the_flaming_fire_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_piccolo_of_the_flaming_fire_SpellScript);
+ PrepareSpellScript(spell_item_piccolo_of_the_flaming_fire);
- void HandleScript(SpellEffIndex effIndex)
- {
- PreventHitDefaultEffect(effIndex);
- if (Player* target = GetHitPlayer())
- target->HandleEmoteCommand(EMOTE_STATE_DANCE);
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_piccolo_of_the_flaming_fire_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ void HandleScript(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ if (Player* target = GetHitPlayer())
+ target->HandleEmoteCommand(EMOTE_STATE_DANCE);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_piccolo_of_the_flaming_fire_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_piccolo_of_the_flaming_fire::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
// http://www.wowhead.com/item=6657 Savory Deviate Delight
@@ -1782,55 +1452,44 @@ enum SavoryDeviateDelight
SPELL_YAAARRRR_FEMALE = 8222,
};
-class spell_item_savory_deviate_delight : public SpellScriptLoader
+class spell_item_savory_deviate_delight : public SpellScript
{
- public:
- spell_item_savory_deviate_delight() : SpellScriptLoader("spell_item_savory_deviate_delight") { }
+ PrepareSpellScript(spell_item_savory_deviate_delight);
- class spell_item_savory_deviate_delight_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_savory_deviate_delight_SpellScript);
-
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_FLIP_OUT_MALE,
- SPELL_FLIP_OUT_FEMALE,
- SPELL_YAAARRRR_MALE,
- SPELL_YAAARRRR_FEMALE
- });
- }
-
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- Unit* caster = GetCaster();
- uint32 spellId = 0;
- switch (urand(1, 2))
- {
- // Flip Out - ninja
- case 1: spellId = (caster->getGender() == GENDER_MALE ? SPELL_FLIP_OUT_MALE : SPELL_FLIP_OUT_FEMALE); break;
- // Yaaarrrr - pirate
- case 2: spellId = (caster->getGender() == GENDER_MALE ? SPELL_YAAARRRR_MALE : SPELL_YAAARRRR_FEMALE); break;
- }
- caster->CastSpell(caster, spellId, true, nullptr);
- }
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- void Register() override
- {
- OnEffectHit += SpellEffectFn(spell_item_savory_deviate_delight_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
+ {
+ SPELL_FLIP_OUT_MALE,
+ SPELL_FLIP_OUT_FEMALE,
+ SPELL_YAAARRRR_MALE,
+ SPELL_YAAARRRR_FEMALE
+ });
+ }
- SpellScript* GetSpellScript() const override
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ uint32 spellId = 0;
+ switch (urand(1, 2))
{
- return new spell_item_savory_deviate_delight_SpellScript();
+ // Flip Out - ninja
+ case 1: spellId = (caster->getGender() == GENDER_MALE ? SPELL_FLIP_OUT_MALE : SPELL_FLIP_OUT_FEMALE); break;
+ // Yaaarrrr - pirate
+ case 2: spellId = (caster->getGender() == GENDER_MALE ? SPELL_YAAARRRR_MALE : SPELL_YAAARRRR_FEMALE); break;
}
+ caster->CastSpell(caster, spellId, true, nullptr);
+ }
+
+ void Register() override
+ {
+ OnEffectHit += SpellEffectFn(spell_item_savory_deviate_delight::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
// 48129 - Scroll of Recall
@@ -1846,64 +1505,53 @@ enum ScrollOfRecall
SPELL_SCROLL_OF_RECALL_FAIL_HORDE_1 = 60328,
};
-class spell_item_scroll_of_recall : public SpellScriptLoader
+class spell_item_scroll_of_recall : public SpellScript
{
- public:
- spell_item_scroll_of_recall() : SpellScriptLoader("spell_item_scroll_of_recall") { }
-
- class spell_item_scroll_of_recall_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_scroll_of_recall_SpellScript);
-
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
+ PrepareSpellScript(spell_item_scroll_of_recall);
- void HandleScript(SpellEffIndex effIndex)
- {
- Unit* caster = GetCaster();
- uint8 maxSafeLevel = 0;
- switch (GetSpellInfo()->Id)
- {
- case SPELL_SCROLL_OF_RECALL_I: // Scroll of Recall
- maxSafeLevel = 40;
- break;
- case SPELL_SCROLL_OF_RECALL_II: // Scroll of Recall II
- maxSafeLevel = 70;
- break;
- case SPELL_SCROLL_OF_RECALL_III: // Scroll of Recal III
- maxSafeLevel = 80;
- break;
- default:
- break;
- }
-
- if (caster->getLevel() > maxSafeLevel)
- {
- caster->CastSpell(caster, SPELL_LOST, true);
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- // ALLIANCE from 60323 to 60330 - HORDE from 60328 to 60335
- uint32 spellId = SPELL_SCROLL_OF_RECALL_FAIL_ALLIANCE_1;
- if (GetCaster()->ToPlayer()->GetTeam() == HORDE)
- spellId = SPELL_SCROLL_OF_RECALL_FAIL_HORDE_1;
+ void HandleScript(SpellEffIndex effIndex)
+ {
+ Unit* caster = GetCaster();
+ uint8 maxSafeLevel = 0;
+ switch (GetSpellInfo()->Id)
+ {
+ case SPELL_SCROLL_OF_RECALL_I: // Scroll of Recall
+ maxSafeLevel = 40;
+ break;
+ case SPELL_SCROLL_OF_RECALL_II: // Scroll of Recall II
+ maxSafeLevel = 70;
+ break;
+ case SPELL_SCROLL_OF_RECALL_III: // Scroll of Recal III
+ maxSafeLevel = 80;
+ break;
+ default:
+ break;
+ }
- GetCaster()->CastSpell(GetCaster(), spellId + urand(0, 7), true);
+ if (caster->getLevel() > maxSafeLevel)
+ {
+ caster->CastSpell(caster, SPELL_LOST, true);
- PreventHitDefaultEffect(effIndex);
- }
- }
+ // ALLIANCE from 60323 to 60330 - HORDE from 60328 to 60335
+ uint32 spellId = SPELL_SCROLL_OF_RECALL_FAIL_ALLIANCE_1;
+ if (GetCaster()->ToPlayer()->GetTeam() == HORDE)
+ spellId = SPELL_SCROLL_OF_RECALL_FAIL_HORDE_1;
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_scroll_of_recall_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_TELEPORT_UNITS);
- }
- };
+ GetCaster()->CastSpell(GetCaster(), spellId + urand(0, 7), true);
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_scroll_of_recall_SpellScript();
+ PreventHitDefaultEffect(effIndex);
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_scroll_of_recall::HandleScript, EFFECT_0, SPELL_EFFECT_TELEPORT_UNITS);
+ }
};
// 71169 - Shadow's Fate (Shadowmourne questline)
@@ -1913,71 +1561,49 @@ enum ShadowsFate
NPC_SINDRAGOSA = 36853
};
-class spell_item_unsated_craving : public SpellScriptLoader
+class spell_item_unsated_craving : public AuraScript
{
- public:
- spell_item_unsated_craving() : SpellScriptLoader("spell_item_unsated_craving") { }
-
- class spell_item_unsated_craving_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_unsated_craving_AuraScript);
+ PrepareAuraScript(spell_item_unsated_craving);
- bool CheckProc(ProcEventInfo& procInfo)
- {
- Unit* caster = procInfo.GetActor();
- if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
- return false;
-
- Unit* target = procInfo.GetActionTarget();
- if (!target || target->GetTypeId() != TYPEID_UNIT || target->IsCritter() || (target->GetEntry() != NPC_SINDRAGOSA && target->IsSummon()))
- return false;
+ bool CheckProc(ProcEventInfo& procInfo)
+ {
+ Unit* caster = procInfo.GetActor();
+ if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
+ return false;
- return true;
- }
+ Unit* target = procInfo.GetActionTarget();
+ if (!target || target->GetTypeId() != TYPEID_UNIT || target->IsCritter() || (target->GetEntry() != NPC_SINDRAGOSA && target->IsSummon()))
+ return false;
- void Register() override
- {
- DoCheckProc += AuraCheckProcFn(spell_item_unsated_craving_AuraScript::CheckProc);
- }
- };
+ return true;
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_unsated_craving_AuraScript();
- }
+ void Register() override
+ {
+ DoCheckProc += AuraCheckProcFn(spell_item_unsated_craving::CheckProc);
+ }
};
-class spell_item_shadows_fate : public SpellScriptLoader
+class spell_item_shadows_fate : public AuraScript
{
- public:
- spell_item_shadows_fate() : SpellScriptLoader("spell_item_shadows_fate") { }
-
- class spell_item_shadows_fate_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_shadows_fate_AuraScript);
+ PrepareAuraScript(spell_item_shadows_fate);
- void HandleProc(ProcEventInfo& procInfo)
- {
- PreventDefaultAction();
-
- Unit* caster = procInfo.GetActor();
- Unit* target = GetCaster();
- if (!caster || !target)
- return;
+ void HandleProc(ProcEventInfo& procInfo)
+ {
+ PreventDefaultAction();
- caster->CastSpell(target, SPELL_SOUL_FEAST, TRIGGERED_FULL_MASK);
- }
+ Unit* caster = procInfo.GetActor();
+ Unit* target = GetCaster();
+ if (!caster || !target)
+ return;
- void Register() override
- {
- OnProc += AuraProcFn(spell_item_shadows_fate_AuraScript::HandleProc);
- }
- };
+ caster->CastSpell(target, SPELL_SOUL_FEAST, true);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_shadows_fate_AuraScript();
- }
+ void Register() override
+ {
+ OnProc += AuraProcFn(spell_item_shadows_fate::HandleProc);
+ }
};
enum Shadowmourne
@@ -1990,120 +1616,98 @@ enum Shadowmourne
};
// 71903 - Item - Shadowmourne Legendary
-class spell_item_shadowmourne : public SpellScriptLoader
+class spell_item_shadowmourne : public AuraScript
{
- public:
- spell_item_shadowmourne() : SpellScriptLoader("spell_item_shadowmourne") { }
+ PrepareAuraScript(spell_item_shadowmourne);
- class spell_item_shadowmourne_AuraScript : public AuraScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareAuraScript(spell_item_shadowmourne_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_SHADOWMOURNE_CHAOS_BANE_DAMAGE,
- SPELL_SHADOWMOURNE_SOUL_FRAGMENT,
- SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF
- });
- }
-
- bool CheckProc(ProcEventInfo& eventInfo)
- {
- if (GetTarget()->HasAura(SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF)) // cant collect shards while under effect of Chaos Bane buff
- return false;
- return eventInfo.GetProcTarget() && eventInfo.GetProcTarget()->IsAlive();
- }
+ SPELL_SHADOWMOURNE_CHAOS_BANE_DAMAGE,
+ SPELL_SHADOWMOURNE_SOUL_FRAGMENT,
+ SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF
+ });
+ }
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
- GetTarget()->CastSpell(GetTarget(), SPELL_SHADOWMOURNE_SOUL_FRAGMENT, true, nullptr, aurEff);
+ bool CheckProc(ProcEventInfo& eventInfo)
+ {
+ if (GetTarget()->HasAura(SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF)) // cant collect shards while under effect of Chaos Bane buff
+ return false;
+ return eventInfo.GetProcTarget() && eventInfo.GetProcTarget()->IsAlive();
+ }
- // this can't be handled in AuraScript of SoulFragments because we need to know victim
- if (Aura* soulFragments = GetTarget()->GetAura(SPELL_SHADOWMOURNE_SOUL_FRAGMENT))
- {
- if (soulFragments->GetStackAmount() >= 10)
- {
- GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_SHADOWMOURNE_CHAOS_BANE_DAMAGE, true, nullptr, aurEff);
- soulFragments->Remove();
- }
- }
- }
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+ GetTarget()->CastSpell(GetTarget(), SPELL_SHADOWMOURNE_SOUL_FRAGMENT, true, nullptr, aurEff);
- void Register() override
+ // this can't be handled in AuraScript of SoulFragments because we need to know victim
+ if (Aura* soulFragments = GetTarget()->GetAura(SPELL_SHADOWMOURNE_SOUL_FRAGMENT))
+ {
+ if (soulFragments->GetStackAmount() >= 10)
{
- DoCheckProc += AuraCheckProcFn(spell_item_shadowmourne_AuraScript::CheckProc);
- OnEffectProc += AuraEffectProcFn(spell_item_shadowmourne_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
+ GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_SHADOWMOURNE_CHAOS_BANE_DAMAGE, true, nullptr, aurEff);
+ soulFragments->Remove();
}
- };
-
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_shadowmourne_AuraScript();
}
+ }
+
+ void Register() override
+ {
+ DoCheckProc += AuraCheckProcFn(spell_item_shadowmourne::CheckProc);
+ OnEffectProc += AuraEffectProcFn(spell_item_shadowmourne::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
+ }
};
// 71905 - Soul Fragment
-class spell_item_shadowmourne_soul_fragment : public SpellScriptLoader
+class spell_item_shadowmourne_soul_fragment : public AuraScript
{
- public:
- spell_item_shadowmourne_soul_fragment() : SpellScriptLoader("spell_item_shadowmourne_soul_fragment") { }
+ PrepareAuraScript(spell_item_shadowmourne_soul_fragment);
- class spell_item_shadowmourne_soul_fragment_AuraScript : public AuraScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareAuraScript(spell_item_shadowmourne_soul_fragment_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_SHADOWMOURNE_VISUAL_LOW,
- SPELL_SHADOWMOURNE_VISUAL_HIGH,
- SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF
- });
- }
-
- void OnStackChange(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- Unit* target = GetTarget();
- switch (GetStackAmount())
- {
- case 1:
- target->CastSpell(target, SPELL_SHADOWMOURNE_VISUAL_LOW, true);
- break;
- case 6:
- target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_LOW);
- target->CastSpell(target, SPELL_SHADOWMOURNE_VISUAL_HIGH, true);
- break;
- case 10:
- target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_HIGH);
- target->CastSpell(target, SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF, true);
- break;
- default:
- break;
- }
- }
+ SPELL_SHADOWMOURNE_VISUAL_LOW,
+ SPELL_SHADOWMOURNE_VISUAL_HIGH,
+ SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF
+ });
+ }
- void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- Unit* target = GetTarget();
+ void OnStackChange(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* target = GetTarget();
+ switch (GetStackAmount())
+ {
+ case 1:
+ target->CastSpell(target, SPELL_SHADOWMOURNE_VISUAL_LOW, true);
+ break;
+ case 6:
target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_LOW);
+ target->CastSpell(target, SPELL_SHADOWMOURNE_VISUAL_HIGH, true);
+ break;
+ case 10:
target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_HIGH);
- }
+ target->CastSpell(target, SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF, true);
+ break;
+ default:
+ break;
+ }
+ }
- void Register() override
- {
- AfterEffectApply += AuraEffectApplyFn(spell_item_shadowmourne_soul_fragment_AuraScript::OnStackChange, EFFECT_0, SPELL_AURA_MOD_STAT, AuraEffectHandleModes(AURA_EFFECT_HANDLE_REAL | AURA_EFFECT_HANDLE_REAPPLY));
- AfterEffectRemove += AuraEffectRemoveFn(spell_item_shadowmourne_soul_fragment_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_REAL);
- }
- };
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* target = GetTarget();
+ target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_LOW);
+ target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_HIGH);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_shadowmourne_soul_fragment_AuraScript();
- }
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_item_shadowmourne_soul_fragment::OnStackChange, EFFECT_0, SPELL_AURA_MOD_STAT, AuraEffectHandleModes(AURA_EFFECT_HANDLE_REAL | AURA_EFFECT_HANDLE_REAPPLY));
+ AfterEffectRemove += AuraEffectRemoveFn(spell_item_shadowmourne_soul_fragment::OnRemove, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_REAL);
+ }
};
// http://www.wowhead.com/item=7734 Six Demon Bag
@@ -2118,69 +1722,58 @@ enum SixDemonBagSpells
SPELL_ENVELOPING_WINDS = 25189,
};
-class spell_item_six_demon_bag : public SpellScriptLoader
+class spell_item_six_demon_bag : public SpellScript
{
- public:
- spell_item_six_demon_bag() : SpellScriptLoader("spell_item_six_demon_bag") { }
-
- class spell_item_six_demon_bag_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_six_demon_bag_SpellScript);
+ PrepareSpellScript(spell_item_six_demon_bag);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_FROSTBOLT,
- SPELL_POLYMORPH,
- SPELL_SUMMON_FELHOUND_MINION,
- SPELL_FIREBALL,
- SPELL_CHAIN_LIGHTNING,
- SPELL_ENVELOPING_WINDS
- });
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
+ {
+ SPELL_FROSTBOLT,
+ SPELL_POLYMORPH,
+ SPELL_SUMMON_FELHOUND_MINION,
+ SPELL_FIREBALL,
+ SPELL_CHAIN_LIGHTNING,
+ SPELL_ENVELOPING_WINDS
+ });
+ }
- void HandleDummy(SpellEffIndex /*effIndex*/)
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ if (Unit* target = GetHitUnit())
+ {
+ uint32 spellId = 0;
+ uint32 rand = urand(0, 99);
+ if (rand < 25) // Fireball (25% chance)
+ spellId = SPELL_FIREBALL;
+ else if (rand < 50) // Frostball (25% chance)
+ spellId = SPELL_FROSTBOLT;
+ else if (rand < 70) // Chain Lighting (20% chance)
+ spellId = SPELL_CHAIN_LIGHTNING;
+ else if (rand < 80) // Polymorph (10% chance)
{
- Unit* caster = GetCaster();
- if (Unit* target = GetHitUnit())
- {
- uint32 spellId = 0;
- uint32 rand = urand(0, 99);
- if (rand < 25) // Fireball (25% chance)
- spellId = SPELL_FIREBALL;
- else if (rand < 50) // Frostball (25% chance)
- spellId = SPELL_FROSTBOLT;
- else if (rand < 70) // Chain Lighting (20% chance)
- spellId = SPELL_CHAIN_LIGHTNING;
- else if (rand < 80) // Polymorph (10% chance)
- {
- spellId = SPELL_POLYMORPH;
- if (urand(0, 100) <= 30) // 30% chance to self-cast
- target = caster;
- }
- else if (rand < 95) // Enveloping Winds (15% chance)
- spellId = SPELL_ENVELOPING_WINDS;
- else // Summon Felhund minion (5% chance)
- {
- spellId = SPELL_SUMMON_FELHOUND_MINION;
- target = caster;
- }
-
- caster->CastSpell(target, spellId, true, GetCastItem());
- }
+ spellId = SPELL_POLYMORPH;
+ if (urand(0, 100) <= 30) // 30% chance to self-cast
+ target = caster;
}
-
- void Register() override
+ else if (rand < 95) // Enveloping Winds (15% chance)
+ spellId = SPELL_ENVELOPING_WINDS;
+ else // Summon Felhund minion (5% chance)
{
- OnEffectHitTarget += SpellEffectFn(spell_item_six_demon_bag_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ spellId = SPELL_SUMMON_FELHOUND_MINION;
+ target = caster;
}
- };
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_six_demon_bag_SpellScript();
+ caster->CastSpell(target, spellId, true, GetCastItem());
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_six_demon_bag::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum SwiftHandJusticeMisc
@@ -2189,39 +1782,28 @@ enum SwiftHandJusticeMisc
};
// 59906 - Swift Hand of Justice Dummy
-class spell_item_swift_hand_justice_dummy : public SpellScriptLoader
+class spell_item_swift_hand_justice_dummy : public AuraScript
{
- public:
- spell_item_swift_hand_justice_dummy() : SpellScriptLoader("spell_item_swift_hand_justice_dummy") { }
-
- class spell_item_swift_hand_justice_dummy_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_swift_hand_justice_dummy_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_SWIFT_HAND_OF_JUSTICE_HEAL });
- }
+ PrepareAuraScript(spell_item_swift_hand_justice_dummy);
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SWIFT_HAND_OF_JUSTICE_HEAL });
+ }
- Unit* caster = eventInfo.GetActor();
- int32 amount = caster->CountPctFromMaxHealth(aurEff->GetAmount());
- caster->CastCustomSpell(SPELL_SWIFT_HAND_OF_JUSTICE_HEAL, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff);
- }
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
- void Register() override
- {
- OnEffectProc += AuraEffectProcFn(spell_item_swift_hand_justice_dummy_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
- }
- };
+ Unit* caster = eventInfo.GetActor();
+ int32 amount = caster->CountPctFromMaxHealth(aurEff->GetAmount());
+ caster->CastCustomSpell(SPELL_SWIFT_HAND_OF_JUSTICE_HEAL, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff);
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_swift_hand_justice_dummy_AuraScript();
- }
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_item_swift_hand_justice_dummy::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
+ }
};
enum TotemOfFlowingWater
@@ -2231,66 +1813,43 @@ enum TotemOfFlowingWater
// Item - 23005: Totem of Flowing Water
// 28849 - Lesser Healing Wave
-class spell_item_totem_of_flowing_water : public SpellScriptLoader
+class spell_item_totem_of_flowing_water : public AuraScript
{
- public:
- spell_item_totem_of_flowing_water() : SpellScriptLoader("spell_item_totem_of_flowing_water") { }
-
- class spell_item_totem_of_flowing_water_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_totem_of_flowing_water_AuraScript);
+ PrepareAuraScript(spell_item_totem_of_flowing_water);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_LESSER_HEALING_WAVE_MANA });
- }
-
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_LESSER_HEALING_WAVE_MANA, true, nullptr, aurEff);
- }
-
- void Register() override
- {
- OnEffectProc += AuraEffectProcFn(spell_item_totem_of_flowing_water_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
- }
- };
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_LESSER_HEALING_WAVE_MANA });
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_totem_of_flowing_water_AuraScript();
- }
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+ eventInfo.GetActor()->CastSpell(nullptr, SPELL_LESSER_HEALING_WAVE_MANA, true, nullptr, aurEff);
+ }
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_item_totem_of_flowing_water::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
+ }
};
// 28862 - The Eye of Diminution
-class spell_item_the_eye_of_diminution : public SpellScriptLoader
+class spell_item_the_eye_of_diminution : public AuraScript
{
- public:
- spell_item_the_eye_of_diminution() : SpellScriptLoader("spell_item_the_eye_of_diminution") { }
-
- class spell_item_the_eye_of_diminution_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_item_the_eye_of_diminution_AuraScript);
+ PrepareAuraScript(spell_item_the_eye_of_diminution);
- void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
- {
- int32 diff = GetUnitOwner()->getLevel() - 60;
- if (diff > 0)
- amount += diff;
- }
-
- void Register() override
- {
- DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_item_the_eye_of_diminution_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_THREAT);
- }
- };
+ void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
+ {
+ int32 diff = GetUnitOwner()->getLevel() - 60;
+ if (diff > 0)
+ amount += diff;
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_item_the_eye_of_diminution_AuraScript();
- }
+ void Register() override
+ {
+ DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_item_the_eye_of_diminution::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_THREAT);
+ }
};
// http://www.wowhead.com/item=44012 Underbelly Elixir
@@ -2302,102 +1861,80 @@ enum UnderbellyElixirSpells
SPELL_UNDERBELLY_ELIXIR_TRIGGERED3 = 59843,
};
-class spell_item_underbelly_elixir : public SpellScriptLoader
+class spell_item_underbelly_elixir : public SpellScript
{
- public:
- spell_item_underbelly_elixir() : SpellScriptLoader("spell_item_underbelly_elixir") { }
+ PrepareSpellScript(spell_item_underbelly_elixir);
- class spell_item_underbelly_elixir_SpellScript : public SpellScript
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareSpellScript(spell_item_underbelly_elixir_SpellScript);
-
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_UNDERBELLY_ELIXIR_TRIGGERED1,
- SPELL_UNDERBELLY_ELIXIR_TRIGGERED2,
- SPELL_UNDERBELLY_ELIXIR_TRIGGERED3
- });
- }
-
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- Unit* caster = GetCaster();
- uint32 spellId = SPELL_UNDERBELLY_ELIXIR_TRIGGERED3;
- switch (urand(1, 3))
- {
- case 1: spellId = SPELL_UNDERBELLY_ELIXIR_TRIGGERED1; break;
- case 2: spellId = SPELL_UNDERBELLY_ELIXIR_TRIGGERED2; break;
- }
- caster->CastSpell(caster, spellId, true, nullptr);
- }
-
- void Register() override
- {
- OnEffectHit += SpellEffectFn(spell_item_underbelly_elixir_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ SPELL_UNDERBELLY_ELIXIR_TRIGGERED1,
+ SPELL_UNDERBELLY_ELIXIR_TRIGGERED2,
+ SPELL_UNDERBELLY_ELIXIR_TRIGGERED3
+ });
+ }
- SpellScript* GetSpellScript() const override
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ uint32 spellId = SPELL_UNDERBELLY_ELIXIR_TRIGGERED3;
+ switch (urand(1, 3))
{
- return new spell_item_underbelly_elixir_SpellScript();
+ case 1: spellId = SPELL_UNDERBELLY_ELIXIR_TRIGGERED1; break;
+ case 2: spellId = SPELL_UNDERBELLY_ELIXIR_TRIGGERED2; break;
}
+ caster->CastSpell(caster, spellId, true, nullptr);
+ }
+
+ void Register() override
+ {
+ OnEffectHit += SpellEffectFn(spell_item_underbelly_elixir::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
// 47776 - Roll 'dem Bones
-class spell_item_worn_troll_dice : public SpellScriptLoader
+class spell_item_worn_troll_dice : public SpellScript
{
- public:
- spell_item_worn_troll_dice() : SpellScriptLoader("spell_item_worn_troll_dice") { }
-
- class spell_item_worn_troll_dice_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_worn_troll_dice_SpellScript);
-
- enum
- {
- TEXT_WORN_TROLL_DICE = 26152
- };
+ PrepareSpellScript(spell_item_worn_troll_dice);
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- if (!sObjectMgr->GetBroadcastText(TEXT_WORN_TROLL_DICE))
- return false;
- return true;
- }
+ enum
+ {
+ TEXT_WORN_TROLL_DICE = 26152
+ };
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sObjectMgr->GetBroadcastText(TEXT_WORN_TROLL_DICE))
+ return false;
+ return true;
+ }
- void HandleScript(SpellEffIndex /*effIndex*/)
- {
- GetCaster()->TextEmote(TEXT_WORN_TROLL_DICE, GetHitUnit());
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- static uint32 const minimum = 1;
- static uint32 const maximum = 6;
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->TextEmote(TEXT_WORN_TROLL_DICE, GetHitUnit());
- // roll twice
- GetCaster()->ToPlayer()->DoRandomRoll(minimum, maximum);
- GetCaster()->ToPlayer()->DoRandomRoll(minimum, maximum);
- }
+ static uint32 const minimum = 1;
+ static uint32 const maximum = 6;
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_worn_troll_dice_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ // roll twice
+ GetCaster()->ToPlayer()->DoRandomRoll(minimum, maximum);
+ GetCaster()->ToPlayer()->DoRandomRoll(minimum, maximum);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_worn_troll_dice_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_worn_troll_dice::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
enum AirRifleSpells
@@ -2407,52 +1944,41 @@ enum AirRifleSpells
SPELL_AIR_RIFLE_SHOOT_SELF = 65577,
};
-class spell_item_red_rider_air_rifle : public SpellScriptLoader
+class spell_item_red_rider_air_rifle : public SpellScript
{
- public:
- spell_item_red_rider_air_rifle() : SpellScriptLoader("spell_item_red_rider_air_rifle") { }
+ PrepareSpellScript(spell_item_red_rider_air_rifle);
- class spell_item_red_rider_air_rifle_SpellScript : public SpellScript
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareSpellScript(spell_item_red_rider_air_rifle_SpellScript);
-
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_AIR_RIFLE_HOLD_VISUAL,
- SPELL_AIR_RIFLE_SHOOT,
- SPELL_AIR_RIFLE_SHOOT_SELF
- });
- }
-
- void HandleScript(SpellEffIndex effIndex)
- {
- PreventHitDefaultEffect(effIndex);
- Unit* caster = GetCaster();
- if (Unit* target = GetHitUnit())
- {
- caster->CastSpell(caster, SPELL_AIR_RIFLE_HOLD_VISUAL, true);
- // needed because this spell shares GCD with its triggered spells (which must not be cast with triggered flag)
- if (Player* player = caster->ToPlayer())
- player->GetSpellHistory()->CancelGlobalCooldown(GetSpellInfo());
- if (urand(0, 4))
- caster->CastSpell(target, SPELL_AIR_RIFLE_SHOOT, false);
- else
- caster->CastSpell(caster, SPELL_AIR_RIFLE_SHOOT_SELF, false);
- }
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_red_rider_air_rifle_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ SPELL_AIR_RIFLE_HOLD_VISUAL,
+ SPELL_AIR_RIFLE_SHOOT,
+ SPELL_AIR_RIFLE_SHOOT_SELF
+ });
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_red_rider_air_rifle_SpellScript();
+ void HandleScript(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ Unit* caster = GetCaster();
+ if (Unit* target = GetHitUnit())
+ {
+ caster->CastSpell(caster, SPELL_AIR_RIFLE_HOLD_VISUAL, true);
+ // needed because this spell shares GCD with its triggered spells (which must not be cast with triggered flag)
+ if (Player* player = caster->ToPlayer())
+ player->GetSpellHistory()->CancelGlobalCooldown(GetSpellInfo());
+ if (urand(0, 4))
+ caster->CastSpell(target, SPELL_AIR_RIFLE_SHOOT, false);
+ else
+ caster->CastSpell(caster, SPELL_AIR_RIFLE_SHOOT_SELF, false);
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_red_rider_air_rifle::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
enum GenericData
@@ -2475,83 +2001,61 @@ enum CreateHeartCandy
ITEM_HEART_CANDY_8 = 21820,
};
-class spell_item_create_heart_candy : public SpellScriptLoader
+class spell_item_create_heart_candy : public SpellScript
{
- public:
- spell_item_create_heart_candy() : SpellScriptLoader("spell_item_create_heart_candy") { }
-
- class spell_item_create_heart_candy_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_create_heart_candy_SpellScript);
+ PrepareSpellScript(spell_item_create_heart_candy);
- void HandleScript(SpellEffIndex effIndex)
- {
- PreventHitDefaultEffect(effIndex);
- if (Player* target = GetHitPlayer())
- {
- static const uint32 items[] = {ITEM_HEART_CANDY_1, ITEM_HEART_CANDY_2, ITEM_HEART_CANDY_3, ITEM_HEART_CANDY_4, ITEM_HEART_CANDY_5, ITEM_HEART_CANDY_6, ITEM_HEART_CANDY_7, ITEM_HEART_CANDY_8};
- target->AddItem(items[urand(0, 7)], 1);
- }
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_create_heart_candy_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
-
- SpellScript* GetSpellScript() const override
+ void HandleScript(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ if (Player* target = GetHitPlayer())
{
- return new spell_item_create_heart_candy_SpellScript();
+ static const uint32 items[] = {ITEM_HEART_CANDY_1, ITEM_HEART_CANDY_2, ITEM_HEART_CANDY_3, ITEM_HEART_CANDY_4, ITEM_HEART_CANDY_5, ITEM_HEART_CANDY_6, ITEM_HEART_CANDY_7, ITEM_HEART_CANDY_8};
+ target->AddItem(items[urand(0, 7)], 1);
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_create_heart_candy::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
-class spell_item_book_of_glyph_mastery : public SpellScriptLoader
+class spell_item_book_of_glyph_mastery : public SpellScript
{
- public:
- spell_item_book_of_glyph_mastery() : SpellScriptLoader("spell_item_book_of_glyph_mastery") { }
-
- class spell_item_book_of_glyph_mastery_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_book_of_glyph_mastery_SpellScript);
+ PrepareSpellScript(spell_item_book_of_glyph_mastery);
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
-
- SpellCastResult CheckRequirement()
- {
- if (HasDiscoveredAllSpells(GetSpellInfo()->Id, GetCaster()->ToPlayer()))
- {
- SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_LEARNED_EVERYTHING);
- return SPELL_FAILED_CUSTOM_ERROR;
- }
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- return SPELL_CAST_OK;
- }
+ SpellCastResult CheckRequirement()
+ {
+ if (HasDiscoveredAllSpells(GetSpellInfo()->Id, GetCaster()->ToPlayer()))
+ {
+ SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_LEARNED_EVERYTHING);
+ return SPELL_FAILED_CUSTOM_ERROR;
+ }
- void HandleScript(SpellEffIndex /*effIndex*/)
- {
- Player* caster = GetCaster()->ToPlayer();
- uint32 spellId = GetSpellInfo()->Id;
+ return SPELL_CAST_OK;
+ }
- // learn random explicit discovery recipe (if any)
- if (uint32 discoveredSpellId = GetExplicitDiscoverySpell(spellId, caster))
- caster->LearnSpell(discoveredSpellId, false);
- }
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Player* caster = GetCaster()->ToPlayer();
+ uint32 spellId = GetSpellInfo()->Id;
- void Register() override
- {
- OnCheckCast += SpellCheckCastFn(spell_item_book_of_glyph_mastery_SpellScript::CheckRequirement);
- OnEffectHitTarget += SpellEffectFn(spell_item_book_of_glyph_mastery_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
+ // learn random explicit discovery recipe (if any)
+ if (uint32 discoveredSpellId = GetExplicitDiscoverySpell(spellId, caster))
+ caster->LearnSpell(discoveredSpellId, false);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_book_of_glyph_mastery_SpellScript();
- }
+ void Register() override
+ {
+ OnCheckCast += SpellCheckCastFn(spell_item_book_of_glyph_mastery::CheckRequirement);
+ OnEffectHitTarget += SpellEffectFn(spell_item_book_of_glyph_mastery::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
enum GiftOfTheHarvester
@@ -2560,38 +2064,27 @@ enum GiftOfTheHarvester
MAX_GHOULS = 5,
};
-class spell_item_gift_of_the_harvester : public SpellScriptLoader
+class spell_item_gift_of_the_harvester : public SpellScript
{
- public:
- spell_item_gift_of_the_harvester() : SpellScriptLoader("spell_item_gift_of_the_harvester") { }
+ PrepareSpellScript(spell_item_gift_of_the_harvester);
- class spell_item_gift_of_the_harvester_SpellScript : public SpellScript
+ SpellCastResult CheckRequirement()
+ {
+ std::list<Creature*> ghouls;
+ GetCaster()->GetAllMinionsByEntry(ghouls, NPC_GHOUL);
+ if (ghouls.size() >= MAX_GHOULS)
{
- PrepareSpellScript(spell_item_gift_of_the_harvester_SpellScript);
-
- SpellCastResult CheckRequirement()
- {
- std::list<Creature*> ghouls;
- GetCaster()->GetAllMinionsByEntry(ghouls, NPC_GHOUL);
- if (ghouls.size() >= MAX_GHOULS)
- {
- SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_TOO_MANY_GHOULS);
- return SPELL_FAILED_CUSTOM_ERROR;
- }
-
- return SPELL_CAST_OK;
- }
+ SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_TOO_MANY_GHOULS);
+ return SPELL_FAILED_CUSTOM_ERROR;
+ }
- void Register() override
- {
- OnCheckCast += SpellCheckCastFn(spell_item_gift_of_the_harvester_SpellScript::CheckRequirement);
- }
- };
+ return SPELL_CAST_OK;
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_gift_of_the_harvester_SpellScript();
- }
+ void Register() override
+ {
+ OnCheckCast += SpellCheckCastFn(spell_item_gift_of_the_harvester::CheckRequirement);
+ }
};
enum Sinkholes
@@ -2601,37 +2094,26 @@ enum Sinkholes
NPC_NORTHWEST_SINKHOLE = 25666,
};
-class spell_item_map_of_the_geyser_fields : public SpellScriptLoader
+class spell_item_map_of_the_geyser_fields : public SpellScript
{
- public:
- spell_item_map_of_the_geyser_fields() : SpellScriptLoader("spell_item_map_of_the_geyser_fields") { }
+ PrepareSpellScript(spell_item_map_of_the_geyser_fields);
- class spell_item_map_of_the_geyser_fields_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_map_of_the_geyser_fields_SpellScript);
-
- SpellCastResult CheckSinkholes()
- {
- Unit* caster = GetCaster();
- if (caster->FindNearestCreature(NPC_SOUTH_SINKHOLE, 30.0f, true) ||
- caster->FindNearestCreature(NPC_NORTHEAST_SINKHOLE, 30.0f, true) ||
- caster->FindNearestCreature(NPC_NORTHWEST_SINKHOLE, 30.0f, true))
- return SPELL_CAST_OK;
-
- SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_MUST_BE_CLOSE_TO_SINKHOLE);
- return SPELL_FAILED_CUSTOM_ERROR;
- }
-
- void Register() override
- {
- OnCheckCast += SpellCheckCastFn(spell_item_map_of_the_geyser_fields_SpellScript::CheckSinkholes);
- }
- };
+ SpellCastResult CheckSinkholes()
+ {
+ Unit* caster = GetCaster();
+ if (caster->FindNearestCreature(NPC_SOUTH_SINKHOLE, 30.0f, true) ||
+ caster->FindNearestCreature(NPC_NORTHEAST_SINKHOLE, 30.0f, true) ||
+ caster->FindNearestCreature(NPC_NORTHWEST_SINKHOLE, 30.0f, true))
+ return SPELL_CAST_OK;
+
+ SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_MUST_BE_CLOSE_TO_SINKHOLE);
+ return SPELL_FAILED_CUSTOM_ERROR;
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_map_of_the_geyser_fields_SpellScript();
- }
+ void Register() override
+ {
+ OnCheckCast += SpellCheckCastFn(spell_item_map_of_the_geyser_fields::CheckSinkholes);
+ }
};
enum VanquishedClutchesSpells
@@ -2641,42 +2123,31 @@ enum VanquishedClutchesSpells
SPELL_CORRUPTOR = 64984,
};
-class spell_item_vanquished_clutches : public SpellScriptLoader
+class spell_item_vanquished_clutches : public SpellScript
{
- public:
- spell_item_vanquished_clutches() : SpellScriptLoader("spell_item_vanquished_clutches") { }
+ PrepareSpellScript(spell_item_vanquished_clutches);
- class spell_item_vanquished_clutches_SpellScript : public SpellScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareSpellScript(spell_item_vanquished_clutches_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_CRUSHER,
- SPELL_CONSTRICTOR,
- SPELL_CORRUPTOR
- });
- }
-
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- uint32 spellId = RAND(SPELL_CRUSHER, SPELL_CONSTRICTOR, SPELL_CORRUPTOR);
- Unit* caster = GetCaster();
- caster->CastSpell(caster, spellId, true);
- }
+ SPELL_CRUSHER,
+ SPELL_CONSTRICTOR,
+ SPELL_CORRUPTOR
+ });
+ }
- void Register() override
- {
- OnEffectHit += SpellEffectFn(spell_item_vanquished_clutches_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ uint32 spellId = RAND(SPELL_CRUSHER, SPELL_CONSTRICTOR, SPELL_CORRUPTOR);
+ Unit* caster = GetCaster();
+ caster->CastSpell(caster, spellId, true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_vanquished_clutches_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHit += SpellEffectFn(spell_item_vanquished_clutches::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum AshbringerSounds
@@ -2695,43 +2166,32 @@ enum AshbringerSounds
SOUND_ASHBRINGER_12 = 8928, // "Kill them all!"
};
-class spell_item_ashbringer : public SpellScriptLoader
+class spell_item_ashbringer : public SpellScript
{
- public:
- spell_item_ashbringer() : SpellScriptLoader("spell_item_ashbringer") { }
-
- class spell_item_ashbringer_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_ashbringer_SpellScript);
-
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
+ PrepareSpellScript(spell_item_ashbringer);
- void OnDummyEffect(SpellEffIndex effIndex)
- {
- PreventHitDefaultEffect(effIndex);
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- Player* player = GetCaster()->ToPlayer();
- uint32 sound_id = RAND( SOUND_ASHBRINGER_1, SOUND_ASHBRINGER_2, SOUND_ASHBRINGER_3, SOUND_ASHBRINGER_4, SOUND_ASHBRINGER_5, SOUND_ASHBRINGER_6,
- SOUND_ASHBRINGER_7, SOUND_ASHBRINGER_8, SOUND_ASHBRINGER_9, SOUND_ASHBRINGER_10, SOUND_ASHBRINGER_11, SOUND_ASHBRINGER_12 );
+ void OnDummyEffect(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
- // Ashbringers effect (spellID 28441) retriggers every 5 seconds, with a chance of making it say one of the above 12 sounds
- if (urand(0, 60) < 1)
- player->PlayDirectSound(sound_id, player);
- }
+ Player* player = GetCaster()->ToPlayer();
+ uint32 sound_id = RAND( SOUND_ASHBRINGER_1, SOUND_ASHBRINGER_2, SOUND_ASHBRINGER_3, SOUND_ASHBRINGER_4, SOUND_ASHBRINGER_5, SOUND_ASHBRINGER_6,
+ SOUND_ASHBRINGER_7, SOUND_ASHBRINGER_8, SOUND_ASHBRINGER_9, SOUND_ASHBRINGER_10, SOUND_ASHBRINGER_11, SOUND_ASHBRINGER_12 );
- void Register() override
- {
- OnEffectHit += SpellEffectFn(spell_item_ashbringer_SpellScript::OnDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ // Ashbringers effect (spellID 28441) retriggers every 5 seconds, with a chance of making it say one of the above 12 sounds
+ if (urand(0, 60) < 1)
+ player->PlayDirectSound(sound_id, player);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_ashbringer_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHit += SpellEffectFn(spell_item_ashbringer::OnDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum MagicEater
@@ -2744,79 +2204,57 @@ enum MagicEater
SPELL_WELL_FED_5 = 57291,
};
-class spell_magic_eater_food : public SpellScriptLoader
+class spell_magic_eater_food : public AuraScript
{
- public:
- spell_magic_eater_food() : SpellScriptLoader("spell_magic_eater_food") { }
-
- class spell_magic_eater_food_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_magic_eater_food_AuraScript);
+ PrepareAuraScript(spell_magic_eater_food);
- void HandleTriggerSpell(AuraEffect const* /*aurEff*/)
- {
- PreventDefaultAction();
- Unit* target = GetTarget();
- switch (urand(0, 5))
- {
- case 0:
- target->CastSpell(target, SPELL_WILD_MAGIC, true);
- break;
- case 1:
- target->CastSpell(target, SPELL_WELL_FED_1, true);
- break;
- case 2:
- target->CastSpell(target, SPELL_WELL_FED_2, true);
- break;
- case 3:
- target->CastSpell(target, SPELL_WELL_FED_3, true);
- break;
- case 4:
- target->CastSpell(target, SPELL_WELL_FED_4, true);
- break;
- case 5:
- target->CastSpell(target, SPELL_WELL_FED_5, true);
- break;
- }
- }
-
- void Register() override
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_magic_eater_food_AuraScript::HandleTriggerSpell, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
- }
- };
-
- AuraScript* GetAuraScript() const override
- {
- return new spell_magic_eater_food_AuraScript();
+ void HandleTriggerSpell(AuraEffect const* /*aurEff*/)
+ {
+ PreventDefaultAction();
+ Unit* target = GetTarget();
+ switch (urand(0, 5))
+ {
+ case 0:
+ target->CastSpell(target, SPELL_WILD_MAGIC, true);
+ break;
+ case 1:
+ target->CastSpell(target, SPELL_WELL_FED_1, true);
+ break;
+ case 2:
+ target->CastSpell(target, SPELL_WELL_FED_2, true);
+ break;
+ case 3:
+ target->CastSpell(target, SPELL_WELL_FED_3, true);
+ break;
+ case 4:
+ target->CastSpell(target, SPELL_WELL_FED_4, true);
+ break;
+ case 5:
+ target->CastSpell(target, SPELL_WELL_FED_5, true);
+ break;
}
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_magic_eater_food::HandleTriggerSpell, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
};
-class spell_item_shimmering_vessel : public SpellScriptLoader
+class spell_item_shimmering_vessel : public SpellScript
{
- public:
- spell_item_shimmering_vessel() : SpellScriptLoader("spell_item_shimmering_vessel") { }
-
- class spell_item_shimmering_vessel_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_shimmering_vessel_SpellScript);
-
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- if (Creature* target = GetHitCreature())
- target->setDeathState(JUST_RESPAWNED);
- }
+ PrepareSpellScript(spell_item_shimmering_vessel);
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_shimmering_vessel_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ if (Creature* target = GetHitCreature())
+ target->setDeathState(JUST_RESPAWNED);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_shimmering_vessel_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_shimmering_vessel::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum PurifyHelboarMeat
@@ -2825,45 +2263,34 @@ enum PurifyHelboarMeat
SPELL_SUMMON_TOXIC_HELBOAR_MEAT = 29278,
};
-class spell_item_purify_helboar_meat : public SpellScriptLoader
+class spell_item_purify_helboar_meat : public SpellScript
{
- public:
- spell_item_purify_helboar_meat() : SpellScriptLoader("spell_item_purify_helboar_meat") { }
-
- class spell_item_purify_helboar_meat_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_purify_helboar_meat_SpellScript);
-
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
+ PrepareSpellScript(spell_item_purify_helboar_meat);
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_SUMMON_PURIFIED_HELBOAR_MEAT,
- SPELL_SUMMON_TOXIC_HELBOAR_MEAT
- });
- }
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- Unit* caster = GetCaster();
- caster->CastSpell(caster, roll_chance_i(50) ? SPELL_SUMMON_PURIFIED_HELBOAR_MEAT : SPELL_SUMMON_TOXIC_HELBOAR_MEAT, true, nullptr);
- }
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo(
+ {
+ SPELL_SUMMON_PURIFIED_HELBOAR_MEAT,
+ SPELL_SUMMON_TOXIC_HELBOAR_MEAT
+ });
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_purify_helboar_meat_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ Unit* caster = GetCaster();
+ caster->CastSpell(caster, roll_chance_i(50) ? SPELL_SUMMON_PURIFIED_HELBOAR_MEAT : SPELL_SUMMON_TOXIC_HELBOAR_MEAT, true, nullptr);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_purify_helboar_meat_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_purify_helboar_meat::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum CrystalPrison
@@ -2871,42 +2298,31 @@ enum CrystalPrison
OBJECT_IMPRISONED_DOOMGUARD = 179644,
};
-class spell_item_crystal_prison_dummy_dnd : public SpellScriptLoader
+class spell_item_crystal_prison_dummy_dnd : public SpellScript
{
- public:
- spell_item_crystal_prison_dummy_dnd() : SpellScriptLoader("spell_item_crystal_prison_dummy_dnd") { }
-
- class spell_item_crystal_prison_dummy_dnd_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_crystal_prison_dummy_dnd_SpellScript);
-
- bool Validate(SpellInfo const* /*spell*/) override
- {
- if (!sObjectMgr->GetGameObjectTemplate(OBJECT_IMPRISONED_DOOMGUARD))
- return false;
- return true;
- }
+ PrepareSpellScript(spell_item_crystal_prison_dummy_dnd);
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- if (Creature* target = GetHitCreature())
- if (target->isDead() && !target->IsPet())
- {
- GetCaster()->SummonGameObject(OBJECT_IMPRISONED_DOOMGUARD, *target, QuaternionData(), uint32(target->GetRespawnTime()-time(nullptr)));
- target->DespawnOrUnsummon();
- }
- }
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ if (!sObjectMgr->GetGameObjectTemplate(OBJECT_IMPRISONED_DOOMGUARD))
+ return false;
+ return true;
+ }
- void Register() override
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ if (Creature* target = GetHitCreature())
+ if (target->isDead() && !target->IsPet())
{
- OnEffectHitTarget += SpellEffectFn(spell_item_crystal_prison_dummy_dnd_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ GetCaster()->SummonGameObject(OBJECT_IMPRISONED_DOOMGUARD, *target, QuaternionData(), uint32(target->GetRespawnTime()-time(nullptr)));
+ target->DespawnOrUnsummon();
}
- };
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_crystal_prison_dummy_dnd_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_crystal_prison_dummy_dnd::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum ReindeerTransformation
@@ -2918,65 +2334,55 @@ enum ReindeerTransformation
SPELL_REINDEER_60 = 25858,
};
-class spell_item_reindeer_transformation : public SpellScriptLoader
-{
- public:
- spell_item_reindeer_transformation() : SpellScriptLoader("spell_item_reindeer_transformation") { }
-
- class spell_item_reindeer_transformation_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_reindeer_transformation_SpellScript);
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_FLYING_REINDEER_310,
- SPELL_FLYING_REINDEER_280,
- SPELL_FLYING_REINDEER_60,
- SPELL_REINDEER_100,
- SPELL_REINDEER_60
- });
- }
+class spell_item_reindeer_transformation : public SpellScript
+{
+ PrepareSpellScript(spell_item_reindeer_transformation);
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- Unit* caster = GetCaster();
- if (caster->HasAuraType(SPELL_AURA_MOUNTED))
- {
- float flyspeed = caster->GetSpeedRate(MOVE_FLIGHT);
- float speed = caster->GetSpeedRate(MOVE_RUN);
-
- caster->RemoveAurasByType(SPELL_AURA_MOUNTED);
- //5 different spells used depending on mounted speed and if mount can fly or not
-
- if (flyspeed >= 4.1f)
- // Flying Reindeer
- caster->CastSpell(caster, SPELL_FLYING_REINDEER_310, true); //310% flying Reindeer
- else if (flyspeed >= 3.8f)
- // Flying Reindeer
- caster->CastSpell(caster, SPELL_FLYING_REINDEER_280, true); //280% flying Reindeer
- else if (flyspeed >= 1.6f)
- // Flying Reindeer
- caster->CastSpell(caster, SPELL_FLYING_REINDEER_60, true); //60% flying Reindeer
- else if (speed >= 2.0f)
- // Reindeer
- caster->CastSpell(caster, SPELL_REINDEER_100, true); //100% ground Reindeer
- else
- // Reindeer
- caster->CastSpell(caster, SPELL_REINDEER_60, true); //60% ground Reindeer
- }
- }
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo(
+ {
+ SPELL_FLYING_REINDEER_310,
+ SPELL_FLYING_REINDEER_280,
+ SPELL_FLYING_REINDEER_60,
+ SPELL_REINDEER_100,
+ SPELL_REINDEER_60
+ });
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_reindeer_transformation_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ Unit* caster = GetCaster();
+ if (caster->HasAuraType(SPELL_AURA_MOUNTED))
+ {
+ float flyspeed = caster->GetSpeedRate(MOVE_FLIGHT);
+ float speed = caster->GetSpeedRate(MOVE_RUN);
+
+ caster->RemoveAurasByType(SPELL_AURA_MOUNTED);
+ //5 different spells used depending on mounted speed and if mount can fly or not
+
+ if (flyspeed >= 4.1f)
+ // Flying Reindeer
+ caster->CastSpell(caster, SPELL_FLYING_REINDEER_310, true); //310% flying Reindeer
+ else if (flyspeed >= 3.8f)
+ // Flying Reindeer
+ caster->CastSpell(caster, SPELL_FLYING_REINDEER_280, true); //280% flying Reindeer
+ else if (flyspeed >= 1.6f)
+ // Flying Reindeer
+ caster->CastSpell(caster, SPELL_FLYING_REINDEER_60, true); //60% flying Reindeer
+ else if (speed >= 2.0f)
+ // Reindeer
+ caster->CastSpell(caster, SPELL_REINDEER_100, true); //100% ground Reindeer
+ else
+ // Reindeer
+ caster->CastSpell(caster, SPELL_REINDEER_60, true); //60% ground Reindeer
+ }
+ }
- SpellScript* GetSpellScript() const override
+ void Register() override
{
- return new spell_item_reindeer_transformation_SpellScript();
+ OnEffectHitTarget += SpellEffectFn(spell_item_reindeer_transformation::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
@@ -2986,42 +2392,31 @@ enum NighInvulnerability
SPELL_COMPLETE_VULNERABILITY = 30457,
};
-class spell_item_nigh_invulnerability : public SpellScriptLoader
+class spell_item_nigh_invulnerability : public SpellScript
{
- public:
- spell_item_nigh_invulnerability() : SpellScriptLoader("spell_item_nigh_invulnerability") { }
-
- class spell_item_nigh_invulnerability_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_nigh_invulnerability_SpellScript);
-
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo({ SPELL_NIGH_INVULNERABILITY, SPELL_COMPLETE_VULNERABILITY });
- }
-
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- Unit* caster = GetCaster();
- if (Item* castItem = GetCastItem())
- {
- if (roll_chance_i(86)) // Nigh-Invulnerability - success
- caster->CastSpell(caster, SPELL_NIGH_INVULNERABILITY, true, castItem);
- else // Complete Vulnerability - backfire in 14% casts
- caster->CastSpell(caster, SPELL_COMPLETE_VULNERABILITY, true, castItem);
- }
- }
+ PrepareSpellScript(spell_item_nigh_invulnerability);
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_nigh_invulnerability_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_NIGH_INVULNERABILITY, SPELL_COMPLETE_VULNERABILITY });
+ }
- SpellScript* GetSpellScript() const override
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ Unit* caster = GetCaster();
+ if (Item* castItem = GetCastItem())
{
- return new spell_item_nigh_invulnerability_SpellScript();
+ if (roll_chance_i(86)) // Nigh-Invulnerability - success
+ caster->CastSpell(caster, SPELL_NIGH_INVULNERABILITY, true, castItem);
+ else // Complete Vulnerability - backfire in 14% casts
+ caster->CastSpell(caster, SPELL_COMPLETE_VULNERABILITY, true, castItem);
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_nigh_invulnerability::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum Poultryzer
@@ -3030,36 +2425,25 @@ enum Poultryzer
SPELL_POULTRYIZER_BACKFIRE = 30504,
};
-class spell_item_poultryizer : public SpellScriptLoader
+class spell_item_poultryizer : public SpellScript
{
- public:
- spell_item_poultryizer() : SpellScriptLoader("spell_item_poultryizer") { }
+ PrepareSpellScript(spell_item_poultryizer);
- class spell_item_poultryizer_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_poultryizer_SpellScript);
-
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo({ SPELL_POULTRYIZER_SUCCESS, SPELL_POULTRYIZER_BACKFIRE });
- }
-
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- if (GetCastItem() && GetHitUnit())
- GetCaster()->CastSpell(GetHitUnit(), roll_chance_i(80) ? SPELL_POULTRYIZER_SUCCESS : SPELL_POULTRYIZER_BACKFIRE, true, GetCastItem());
- }
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_POULTRYIZER_SUCCESS, SPELL_POULTRYIZER_BACKFIRE });
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_poultryizer_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ if (GetCastItem() && GetHitUnit())
+ GetCaster()->CastSpell(GetHitUnit(), roll_chance_i(80) ? SPELL_POULTRYIZER_SUCCESS : SPELL_POULTRYIZER_BACKFIRE, true, GetCastItem());
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_poultryizer_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_poultryizer::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum SocretharsStone
@@ -3068,50 +2452,39 @@ enum SocretharsStone
SPELL_SOCRETHAR_FROM_SEAT = 35744,
};
-class spell_item_socrethars_stone : public SpellScriptLoader
+class spell_item_socrethars_stone : public SpellScript
{
- public:
- spell_item_socrethars_stone() : SpellScriptLoader("spell_item_socrethars_stone") { }
-
- class spell_item_socrethars_stone_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_socrethars_stone_SpellScript);
-
- bool Load() override
- {
- return (GetCaster()->GetAreaId() == 3900 || GetCaster()->GetAreaId() == 3742);
- }
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo({ SPELL_SOCRETHAR_TO_SEAT, SPELL_SOCRETHAR_FROM_SEAT });
- }
-
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- Unit* caster = GetCaster();
- switch (caster->GetAreaId())
- {
- case 3900:
- caster->CastSpell(caster, SPELL_SOCRETHAR_TO_SEAT, true);
- break;
- case 3742:
- caster->CastSpell(caster, SPELL_SOCRETHAR_FROM_SEAT, true);
- break;
- default:
- return;
- }
- }
+ PrepareSpellScript(spell_item_socrethars_stone);
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_socrethars_stone_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ bool Load() override
+ {
+ return (GetCaster()->GetAreaId() == 3900 || GetCaster()->GetAreaId() == 3742);
+ }
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SOCRETHAR_TO_SEAT, SPELL_SOCRETHAR_FROM_SEAT });
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_socrethars_stone_SpellScript();
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ Unit* caster = GetCaster();
+ switch (caster->GetAreaId())
+ {
+ case 3900:
+ caster->CastSpell(caster, SPELL_SOCRETHAR_TO_SEAT, true);
+ break;
+ case 3742:
+ caster->CastSpell(caster, SPELL_SOCRETHAR_FROM_SEAT, true);
+ break;
+ default:
+ return;
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_socrethars_stone::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum DemonBroiledSurprise
@@ -3121,56 +2494,45 @@ enum DemonBroiledSurprise
NPC_ABYSSAL_FLAMEBRINGER = 19973,
};
-class spell_item_demon_broiled_surprise : public SpellScriptLoader
+class spell_item_demon_broiled_surprise : public SpellScript
{
- public:
- spell_item_demon_broiled_surprise() : SpellScriptLoader("spell_item_demon_broiled_surprise") { }
-
- class spell_item_demon_broiled_surprise_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_demon_broiled_surprise_SpellScript);
+ PrepareSpellScript(spell_item_demon_broiled_surprise);
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo({ SPELL_CREATE_DEMON_BROILED_SURPRISE }) &&
- sObjectMgr->GetCreatureTemplate(NPC_ABYSSAL_FLAMEBRINGER) &&
- sObjectMgr->GetQuestTemplate(QUEST_SUPER_HOT_STEW);
- }
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_CREATE_DEMON_BROILED_SURPRISE }) &&
+ sObjectMgr->GetCreatureTemplate(NPC_ABYSSAL_FLAMEBRINGER) &&
+ sObjectMgr->GetQuestTemplate(QUEST_SUPER_HOT_STEW);
+ }
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- Unit* player = GetCaster();
- player->CastSpell(player, SPELL_CREATE_DEMON_BROILED_SURPRISE, false);
- }
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ Unit* player = GetCaster();
+ player->CastSpell(player, SPELL_CREATE_DEMON_BROILED_SURPRISE, false);
+ }
- SpellCastResult CheckRequirement()
- {
- Player* player = GetCaster()->ToPlayer();
- if (player->GetQuestStatus(QUEST_SUPER_HOT_STEW) != QUEST_STATUS_INCOMPLETE)
- return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW;
-
- if (Creature* creature = player->FindNearestCreature(NPC_ABYSSAL_FLAMEBRINGER, 10, false))
- if (creature->isDead())
- return SPELL_CAST_OK;
- return SPELL_FAILED_NOT_HERE;
- }
+ SpellCastResult CheckRequirement()
+ {
+ Player* player = GetCaster()->ToPlayer();
+ if (player->GetQuestStatus(QUEST_SUPER_HOT_STEW) != QUEST_STATUS_INCOMPLETE)
+ return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW;
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_demon_broiled_surprise_SpellScript::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY);
- OnCheckCast += SpellCheckCastFn(spell_item_demon_broiled_surprise_SpellScript::CheckRequirement);
- }
- };
+ if (Creature* creature = player->FindNearestCreature(NPC_ABYSSAL_FLAMEBRINGER, 10, false))
+ if (creature->isDead())
+ return SPELL_CAST_OK;
+ return SPELL_FAILED_NOT_HERE;
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_demon_broiled_surprise_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_demon_broiled_surprise::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY);
+ OnCheckCast += SpellCheckCastFn(spell_item_demon_broiled_surprise::CheckRequirement);
+ }
};
enum CompleteRaptorCapture
@@ -3178,42 +2540,31 @@ enum CompleteRaptorCapture
SPELL_RAPTOR_CAPTURE_CREDIT = 42337,
};
-class spell_item_complete_raptor_capture : public SpellScriptLoader
+class spell_item_complete_raptor_capture : public SpellScript
{
- public:
- spell_item_complete_raptor_capture() : SpellScriptLoader("spell_item_complete_raptor_capture") { }
-
- class spell_item_complete_raptor_capture_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_complete_raptor_capture_SpellScript);
-
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo({ SPELL_RAPTOR_CAPTURE_CREDIT });
- }
+ PrepareSpellScript(spell_item_complete_raptor_capture);
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- Unit* caster = GetCaster();
- if (GetHitCreature())
- {
- GetHitCreature()->DespawnOrUnsummon();
-
- //cast spell Raptor Capture Credit
- caster->CastSpell(caster, SPELL_RAPTOR_CAPTURE_CREDIT, true, nullptr);
- }
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_complete_raptor_capture_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_RAPTOR_CAPTURE_CREDIT });
+ }
- SpellScript* GetSpellScript() const override
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ Unit* caster = GetCaster();
+ if (GetHitCreature())
{
- return new spell_item_complete_raptor_capture_SpellScript();
+ GetHitCreature()->DespawnOrUnsummon();
+
+ //cast spell Raptor Capture Credit
+ caster->CastSpell(caster, SPELL_RAPTOR_CAPTURE_CREDIT, true, nullptr);
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_complete_raptor_capture::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum ImpaleLeviroth
@@ -3222,42 +2573,31 @@ enum ImpaleLeviroth
SPELL_LEVIROTH_SELF_IMPALE = 49882
};
-class spell_item_impale_leviroth : public SpellScriptLoader
+class spell_item_impale_leviroth : public SpellScript
{
- public:
- spell_item_impale_leviroth() : SpellScriptLoader("spell_item_impale_leviroth") { }
-
- class spell_item_impale_leviroth_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_impale_leviroth_SpellScript);
+ PrepareSpellScript(spell_item_impale_leviroth);
- bool Validate(SpellInfo const* /*spell*/) override
- {
- if (!sObjectMgr->GetCreatureTemplate(NPC_LEVIROTH))
- return false;
- return true;
- }
-
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- if (Creature* target = GetHitCreature())
- if (target->GetEntry() == NPC_LEVIROTH && !target->HealthBelowPct(95))
- {
- target->CastSpell(target, SPELL_LEVIROTH_SELF_IMPALE, true);
- target->ResetPlayerDamageReq();
- }
- }
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ if (!sObjectMgr->GetCreatureTemplate(NPC_LEVIROTH))
+ return false;
+ return true;
+ }
- void Register() override
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ if (Creature* target = GetHitCreature())
+ if (target->GetEntry() == NPC_LEVIROTH && !target->HealthBelowPct(95))
{
- OnEffectHitTarget += SpellEffectFn(spell_item_impale_leviroth_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ target->CastSpell(target, SPELL_LEVIROTH_SELF_IMPALE, true);
+ target->ResetPlayerDamageReq();
}
- };
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_impale_leviroth_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_impale_leviroth::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum BrewfestMountTransformation
@@ -3270,111 +2610,130 @@ enum BrewfestMountTransformation
SPELL_BREWFEST_MOUNT_TRANSFORM_REVERSE = 52845,
};
-class spell_item_brewfest_mount_transformation : public SpellScriptLoader
+class spell_item_brewfest_mount_transformation : public SpellScript
{
- public:
- spell_item_brewfest_mount_transformation() : SpellScriptLoader("spell_item_brewfest_mount_transformation") { }
+ PrepareSpellScript(spell_item_brewfest_mount_transformation);
- class spell_item_brewfest_mount_transformation_SpellScript : public SpellScript
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo(
{
- PrepareSpellScript(spell_item_brewfest_mount_transformation_SpellScript);
+ SPELL_MOUNT_RAM_100,
+ SPELL_MOUNT_RAM_60,
+ SPELL_MOUNT_KODO_100,
+ SPELL_MOUNT_KODO_60
+ });
+ }
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_MOUNT_RAM_100,
- SPELL_MOUNT_RAM_60,
- SPELL_MOUNT_KODO_100,
- SPELL_MOUNT_KODO_60
- });
- }
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ Player* caster = GetCaster()->ToPlayer();
+ if (caster->HasAuraType(SPELL_AURA_MOUNTED))
+ {
+ caster->RemoveAurasByType(SPELL_AURA_MOUNTED);
+ uint32 spell_id;
- void HandleDummy(SpellEffIndex /* effIndex */)
+ switch (GetSpellInfo()->Id)
{
- Player* caster = GetCaster()->ToPlayer();
- if (caster->HasAuraType(SPELL_AURA_MOUNTED))
- {
- caster->RemoveAurasByType(SPELL_AURA_MOUNTED);
- uint32 spell_id;
-
- switch (GetSpellInfo()->Id)
- {
- case SPELL_BREWFEST_MOUNT_TRANSFORM:
- if (caster->GetSpeedRate(MOVE_RUN) >= 2.0f)
- spell_id = caster->GetTeam() == ALLIANCE ? SPELL_MOUNT_RAM_100 : SPELL_MOUNT_KODO_100;
- else
- spell_id = caster->GetTeam() == ALLIANCE ? SPELL_MOUNT_RAM_60 : SPELL_MOUNT_KODO_60;
- break;
- case SPELL_BREWFEST_MOUNT_TRANSFORM_REVERSE:
- if (caster->GetSpeedRate(MOVE_RUN) >= 2.0f)
- spell_id = caster->GetTeam() == HORDE ? SPELL_MOUNT_RAM_100 : SPELL_MOUNT_KODO_100;
- else
- spell_id = caster->GetTeam() == HORDE ? SPELL_MOUNT_RAM_60 : SPELL_MOUNT_KODO_60;
- break;
- default:
- return;
- }
- caster->CastSpell(caster, spell_id, true);
- }
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_brewfest_mount_transformation_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ case SPELL_BREWFEST_MOUNT_TRANSFORM:
+ if (caster->GetSpeedRate(MOVE_RUN) >= 2.0f)
+ spell_id = caster->GetTeam() == ALLIANCE ? SPELL_MOUNT_RAM_100 : SPELL_MOUNT_KODO_100;
+ else
+ spell_id = caster->GetTeam() == ALLIANCE ? SPELL_MOUNT_RAM_60 : SPELL_MOUNT_KODO_60;
+ break;
+ case SPELL_BREWFEST_MOUNT_TRANSFORM_REVERSE:
+ if (caster->GetSpeedRate(MOVE_RUN) >= 2.0f)
+ spell_id = caster->GetTeam() == HORDE ? SPELL_MOUNT_RAM_100 : SPELL_MOUNT_KODO_100;
+ else
+ spell_id = caster->GetTeam() == HORDE ? SPELL_MOUNT_RAM_60 : SPELL_MOUNT_KODO_60;
+ break;
+ default:
+ return;
}
- };
-
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_brewfest_mount_transformation_SpellScript();
+ caster->CastSpell(caster, spell_id, true);
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_brewfest_mount_transformation::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
-enum NitroBoots
+enum NitroBoosts
{
- SPELL_NITRO_BOOTS_SUCCESS = 54861,
- SPELL_NITRO_BOOTS_BACKFIRE = 46014,
+ SPELL_NITRO_BOOSTS_SUCCESS = 54861,
+ SPELL_NITRO_BOOSTS_BACKFIRE = 54621,
+ SPELL_NITRO_BOOSTS_PARACHUTE = 54649,
};
-class spell_item_nitro_boots : public SpellScriptLoader
+class spell_item_nitro_boosts : public SpellScript
{
- public:
- spell_item_nitro_boots() : SpellScriptLoader("spell_item_nitro_boots") { }
+ PrepareSpellScript(spell_item_nitro_boosts);
- class spell_item_nitro_boots_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_nitro_boots_SpellScript);
+ bool Load() override
+ {
+ if (!GetCastItem())
+ return false;
+ return true;
+ }
- bool Load() override
- {
- if (!GetCastItem())
- return false;
- return true;
- }
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_NITRO_BOOSTS_SUCCESS, SPELL_NITRO_BOOSTS_BACKFIRE });
+ }
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo({ SPELL_NITRO_BOOTS_SUCCESS, SPELL_NITRO_BOOTS_BACKFIRE });
- }
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ Unit* caster = GetCaster();
+ AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(caster->GetAreaId());
+ bool success = true;
+ if (areaEntry && areaEntry->IsFlyable() && !caster->GetMap()->IsDungeon())
+ success = roll_chance_i(95); // nitro boosts can only fail in flying-enabled locations on 3.3.5
+ caster->CastSpell(caster, success ? SPELL_NITRO_BOOSTS_SUCCESS : SPELL_NITRO_BOOSTS_BACKFIRE, true, GetCastItem());
+ }
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- Unit* caster = GetCaster();
- bool success = caster->GetMap()->IsDungeon() || roll_chance_i(95);
- caster->CastSpell(caster, success ? SPELL_NITRO_BOOTS_SUCCESS : SPELL_NITRO_BOOTS_BACKFIRE, true, GetCastItem());
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_nitro_boosts::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+};
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_nitro_boots_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+class spell_item_nitro_boosts_backfire : public AuraScript
+{
+ PrepareAuraScript(spell_item_nitro_boosts_backfire);
- SpellScript* GetSpellScript() const override
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_NITRO_BOOSTS_PARACHUTE });
+ }
+
+ void HandleApply(AuraEffect const* /*effect*/, AuraEffectHandleModes /*mode*/)
+ {
+ lastZ = GetTarget()->GetPositionZ();
+ }
+
+ void HandlePeriodicDummy(AuraEffect const* effect)
+ {
+ PreventDefaultAction();
+ float curZ = GetTarget()->GetPositionZ();
+ if (curZ < lastZ)
{
- return new spell_item_nitro_boots_SpellScript();
+ if (roll_chance_i(80)) // we don't have enough sniffs to verify this, guesstimate
+ GetTarget()->CastSpell(GetTarget(), SPELL_NITRO_BOOSTS_PARACHUTE, true, nullptr, effect);
+ GetAura()->Remove();
}
+ else
+ lastZ = curZ;
+ }
+
+ void Register() override
+ {
+ OnEffectApply += AuraEffectApplyFn(spell_item_nitro_boosts_backfire::HandleApply, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_item_nitro_boosts_backfire::HandlePeriodicDummy, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
+
+ float lastZ = INVALID_HEIGHT;
};
enum TeachLanguage
@@ -3383,43 +2742,32 @@ enum TeachLanguage
SPELL_LEARN_GOBLIN_BINARY = 50246,
};
-class spell_item_teach_language : public SpellScriptLoader
+class spell_item_teach_language : public SpellScript
{
- public:
- spell_item_teach_language() : SpellScriptLoader("spell_item_teach_language") { }
-
- class spell_item_teach_language_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_teach_language_SpellScript);
+ PrepareSpellScript(spell_item_teach_language);
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
-
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo({ SPELL_LEARN_GNOMISH_BINARY, SPELL_LEARN_GOBLIN_BINARY });
- }
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- Player* caster = GetCaster()->ToPlayer();
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_LEARN_GNOMISH_BINARY, SPELL_LEARN_GOBLIN_BINARY });
+ }
- if (roll_chance_i(34))
- caster->CastSpell(caster, caster->GetTeam() == ALLIANCE ? SPELL_LEARN_GNOMISH_BINARY : SPELL_LEARN_GOBLIN_BINARY, true);
- }
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ Player* caster = GetCaster()->ToPlayer();
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_teach_language_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ if (roll_chance_i(34))
+ caster->CastSpell(caster, caster->GetTeam() == ALLIANCE ? SPELL_LEARN_GNOMISH_BINARY : SPELL_LEARN_GOBLIN_BINARY, true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_teach_language_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_teach_language::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum RocketBoots
@@ -3427,53 +2775,42 @@ enum RocketBoots
SPELL_ROCKET_BOOTS_PROC = 30452,
};
-class spell_item_rocket_boots : public SpellScriptLoader
+class spell_item_rocket_boots : public SpellScript
{
- public:
- spell_item_rocket_boots() : SpellScriptLoader("spell_item_rocket_boots") { }
-
- class spell_item_rocket_boots_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_rocket_boots_SpellScript);
-
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
+ PrepareSpellScript(spell_item_rocket_boots);
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo({ SPELL_ROCKET_BOOTS_PROC });
- }
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- Player* caster = GetCaster()->ToPlayer();
- if (Battleground* bg = caster->GetBattleground())
- bg->EventPlayerDroppedFlag(caster);
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_ROCKET_BOOTS_PROC });
+ }
- caster->GetSpellHistory()->ResetCooldown(SPELL_ROCKET_BOOTS_PROC);
- caster->CastSpell(caster, SPELL_ROCKET_BOOTS_PROC, true, nullptr);
- }
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ Player* caster = GetCaster()->ToPlayer();
+ if (Battleground* bg = caster->GetBattleground())
+ bg->EventPlayerDroppedFlag(caster);
- SpellCastResult CheckCast()
- {
- if (GetCaster()->IsInWater())
- return SPELL_FAILED_ONLY_ABOVEWATER;
- return SPELL_CAST_OK;
- }
+ caster->GetSpellHistory()->ResetCooldown(SPELL_ROCKET_BOOTS_PROC);
+ caster->CastSpell(caster, SPELL_ROCKET_BOOTS_PROC, true, nullptr);
+ }
- void Register() override
- {
- OnCheckCast += SpellCheckCastFn(spell_item_rocket_boots_SpellScript::CheckCast);
- OnEffectHitTarget += SpellEffectFn(spell_item_rocket_boots_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ SpellCastResult CheckCast()
+ {
+ if (GetCaster()->IsInWater())
+ return SPELL_FAILED_ONLY_ABOVEWATER;
+ return SPELL_CAST_OK;
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_rocket_boots_SpellScript();
- }
+ void Register() override
+ {
+ OnCheckCast += SpellCheckCastFn(spell_item_rocket_boots::CheckCast);
+ OnEffectHitTarget += SpellEffectFn(spell_item_rocket_boots::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum PygmyOil
@@ -3482,75 +2819,53 @@ enum PygmyOil
SPELL_PYGMY_OIL_SMALLER_AURA = 53805,
};
-class spell_item_pygmy_oil : public SpellScriptLoader
+class spell_item_pygmy_oil : public SpellScript
{
- public:
- spell_item_pygmy_oil() : SpellScriptLoader("spell_item_pygmy_oil") { }
+ PrepareSpellScript(spell_item_pygmy_oil);
- class spell_item_pygmy_oil_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_pygmy_oil_SpellScript);
-
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo({ SPELL_PYGMY_OIL_PYGMY_AURA, SPELL_PYGMY_OIL_SMALLER_AURA });
- }
-
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- Unit* caster = GetCaster();
- if (Aura* aura = caster->GetAura(SPELL_PYGMY_OIL_PYGMY_AURA))
- aura->RefreshDuration();
- else
- {
- aura = caster->GetAura(SPELL_PYGMY_OIL_SMALLER_AURA);
- if (!aura || aura->GetStackAmount() < 5 || !roll_chance_i(50))
- caster->CastSpell(caster, SPELL_PYGMY_OIL_SMALLER_AURA, true);
- else
- {
- aura->Remove();
- caster->CastSpell(caster, SPELL_PYGMY_OIL_PYGMY_AURA, true);
- }
- }
- }
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_PYGMY_OIL_PYGMY_AURA, SPELL_PYGMY_OIL_SMALLER_AURA });
+ }
- void Register() override
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ Unit* caster = GetCaster();
+ if (Aura* aura = caster->GetAura(SPELL_PYGMY_OIL_PYGMY_AURA))
+ aura->RefreshDuration();
+ else
+ {
+ aura = caster->GetAura(SPELL_PYGMY_OIL_SMALLER_AURA);
+ if (!aura || aura->GetStackAmount() < 5 || !roll_chance_i(50))
+ caster->CastSpell(caster, SPELL_PYGMY_OIL_SMALLER_AURA, true);
+ else
{
- OnEffectHitTarget += SpellEffectFn(spell_item_pygmy_oil_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ aura->Remove();
+ caster->CastSpell(caster, SPELL_PYGMY_OIL_PYGMY_AURA, true);
}
- };
-
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_pygmy_oil_SpellScript();
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_pygmy_oil::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
-class spell_item_unusual_compass : public SpellScriptLoader
+class spell_item_unusual_compass : public SpellScript
{
- public:
- spell_item_unusual_compass() : SpellScriptLoader("spell_item_unusual_compass") { }
-
- class spell_item_unusual_compass_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_unusual_compass_SpellScript);
+ PrepareSpellScript(spell_item_unusual_compass);
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- Unit* caster = GetCaster();
- caster->SetFacingTo(frand(0.0f, 2.0f * float(M_PI)));
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_unusual_compass_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ Unit* caster = GetCaster();
+ caster->SetFacingTo(frand(0.0f, 2.0f * float(M_PI)));
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_unusual_compass_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_unusual_compass::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum ChickenCover
@@ -3561,50 +2876,39 @@ enum ChickenCover
QUEST_FLOWN_THE_COOP = 12532,
};
-class spell_item_chicken_cover : public SpellScriptLoader
+class spell_item_chicken_cover : public SpellScript
{
- public:
- spell_item_chicken_cover() : SpellScriptLoader("spell_item_chicken_cover") { }
+ PrepareSpellScript(spell_item_chicken_cover);
- class spell_item_chicken_cover_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_chicken_cover_SpellScript);
-
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
-
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo({ SPELL_CHICKEN_NET, SPELL_CAPTURE_CHICKEN_ESCAPE }) &&
- sObjectMgr->GetQuestTemplate(QUEST_CHICKEN_PARTY) &&
- sObjectMgr->GetQuestTemplate(QUEST_FLOWN_THE_COOP);
- }
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- Player* caster = GetCaster()->ToPlayer();
- if (Unit* target = GetHitUnit())
- {
- if (!target->HasAura(SPELL_CHICKEN_NET) && (caster->GetQuestStatus(QUEST_CHICKEN_PARTY) == QUEST_STATUS_INCOMPLETE || caster->GetQuestStatus(QUEST_FLOWN_THE_COOP) == QUEST_STATUS_INCOMPLETE))
- {
- caster->CastSpell(caster, SPELL_CAPTURE_CHICKEN_ESCAPE, true);
- target->KillSelf();
- }
- }
- }
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_CHICKEN_NET, SPELL_CAPTURE_CHICKEN_ESCAPE }) &&
+ sObjectMgr->GetQuestTemplate(QUEST_CHICKEN_PARTY) &&
+ sObjectMgr->GetQuestTemplate(QUEST_FLOWN_THE_COOP);
+ }
- void Register() override
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ Player* caster = GetCaster()->ToPlayer();
+ if (Unit* target = GetHitUnit())
+ {
+ if (!target->HasAura(SPELL_CHICKEN_NET) && (caster->GetQuestStatus(QUEST_CHICKEN_PARTY) == QUEST_STATUS_INCOMPLETE || caster->GetQuestStatus(QUEST_FLOWN_THE_COOP) == QUEST_STATUS_INCOMPLETE))
{
- OnEffectHitTarget += SpellEffectFn(spell_item_chicken_cover_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ caster->CastSpell(caster, SPELL_CAPTURE_CHICKEN_ESCAPE, true);
+ target->KillSelf();
}
- };
-
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_chicken_cover_SpellScript();
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_chicken_cover::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum Refocus
@@ -3614,100 +2918,67 @@ enum Refocus
SPELL_VOLLEY = 42243,
};
-class spell_item_refocus : public SpellScriptLoader
+class spell_item_refocus : public SpellScript
{
- public:
- spell_item_refocus() : SpellScriptLoader("spell_item_refocus") { }
-
- class spell_item_refocus_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_refocus_SpellScript);
-
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- Player* caster = GetCaster()->ToPlayer();
+ PrepareSpellScript(spell_item_refocus);
- if (!caster || caster->getClass() != CLASS_HUNTER)
- return;
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ Player* caster = GetCaster()->ToPlayer();
- if (caster->GetSpellHistory()->HasCooldown(SPELL_AIMED_SHOT))
- caster->GetSpellHistory()->ResetCooldown(SPELL_AIMED_SHOT, true);
+ if (!caster || caster->getClass() != CLASS_HUNTER)
+ return;
- if (caster->GetSpellHistory()->HasCooldown(SPELL_MULTISHOT))
- caster->GetSpellHistory()->ResetCooldown(SPELL_MULTISHOT, true);
+ if (caster->GetSpellHistory()->HasCooldown(SPELL_AIMED_SHOT))
+ caster->GetSpellHistory()->ResetCooldown(SPELL_AIMED_SHOT, true);
- if (caster->GetSpellHistory()->HasCooldown(SPELL_VOLLEY))
- caster->GetSpellHistory()->ResetCooldown(SPELL_VOLLEY, true);
- }
+ if (caster->GetSpellHistory()->HasCooldown(SPELL_MULTISHOT))
+ caster->GetSpellHistory()->ResetCooldown(SPELL_MULTISHOT, true);
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_refocus_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ if (caster->GetSpellHistory()->HasCooldown(SPELL_VOLLEY))
+ caster->GetSpellHistory()->ResetCooldown(SPELL_VOLLEY, true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_refocus_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_refocus::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
-class spell_item_muisek_vessel : public SpellScriptLoader
+class spell_item_muisek_vessel : public SpellScript
{
- public:
- spell_item_muisek_vessel() : SpellScriptLoader("spell_item_muisek_vessel") { }
-
- class spell_item_muisek_vessel_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_muisek_vessel_SpellScript);
+ PrepareSpellScript(spell_item_muisek_vessel);
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- if (Creature* target = GetHitCreature())
- if (target->isDead())
- target->DespawnOrUnsummon();
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_muisek_vessel_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ if (Creature* target = GetHitCreature())
+ if (target->isDead())
+ target->DespawnOrUnsummon();
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_muisek_vessel_SpellScript();
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_muisek_vessel::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum GreatmothersSoulcather
{
SPELL_FORCE_CAST_SUMMON_GNOME_SOUL = 46486,
};
-class spell_item_greatmothers_soulcatcher : public SpellScriptLoader
+class spell_item_greatmothers_soulcatcher : public SpellScript
{
-public:
- spell_item_greatmothers_soulcatcher() : SpellScriptLoader("spell_item_greatmothers_soulcatcher") { }
+ PrepareSpellScript(spell_item_greatmothers_soulcatcher);
- class spell_item_greatmothers_soulcatcher_SpellScript : public SpellScript
+ void HandleDummy(SpellEffIndex /*effIndex*/)
{
- PrepareSpellScript(spell_item_greatmothers_soulcatcher_SpellScript);
-
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- if (GetHitUnit())
- GetCaster()->CastSpell(GetCaster(), SPELL_FORCE_CAST_SUMMON_GNOME_SOUL);
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_greatmothers_soulcatcher_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ if (GetHitUnit())
+ GetCaster()->CastSpell(GetCaster(), SPELL_FORCE_CAST_SUMMON_GNOME_SOUL);
+ }
- SpellScript* GetSpellScript() const override
+ void Register() override
{
- return new spell_item_greatmothers_soulcatcher_SpellScript();
+ OnEffectHitTarget += SpellEffectFn(spell_item_greatmothers_soulcatcher::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
@@ -3778,60 +3049,49 @@ enum SoulPreserver
SPELL_SOUL_PRESERVER_SHAMAN = 60515,
};
-class spell_item_soul_preserver : public SpellScriptLoader
+class spell_item_soul_preserver : public AuraScript
{
-public:
- spell_item_soul_preserver() : SpellScriptLoader("spell_item_soul_preserver") { }
+ PrepareAuraScript(spell_item_soul_preserver);
- class spell_item_soul_preserver_AuraScript : public AuraScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
{
- PrepareAuraScript(spell_item_soul_preserver_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_SOUL_PRESERVER_DRUID,
- SPELL_SOUL_PRESERVER_PALADIN,
- SPELL_SOUL_PRESERVER_PRIEST,
- SPELL_SOUL_PRESERVER_SHAMAN
- });
- }
-
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ return ValidateSpellInfo(
{
- PreventDefaultAction();
-
- Unit* caster = eventInfo.GetActor();
-
- switch (caster->getClass())
- {
- case CLASS_DRUID:
- caster->CastSpell(caster, SPELL_SOUL_PRESERVER_DRUID, true, nullptr, aurEff);
- break;
- case CLASS_PALADIN:
- caster->CastSpell(caster, SPELL_SOUL_PRESERVER_PALADIN, true, nullptr, aurEff);
- break;
- case CLASS_PRIEST:
- caster->CastSpell(caster, SPELL_SOUL_PRESERVER_PRIEST, true, nullptr, aurEff);
- break;
- case CLASS_SHAMAN:
- caster->CastSpell(caster, SPELL_SOUL_PRESERVER_SHAMAN, true, nullptr, aurEff);
- break;
- default:
- break;
- }
- }
+ SPELL_SOUL_PRESERVER_DRUID,
+ SPELL_SOUL_PRESERVER_PALADIN,
+ SPELL_SOUL_PRESERVER_PRIEST,
+ SPELL_SOUL_PRESERVER_SHAMAN
+ });
+ }
- void Register() override
- {
- OnEffectProc += AuraEffectProcFn(spell_item_soul_preserver_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+
+ Unit* caster = eventInfo.GetActor();
+
+ switch (caster->getClass())
+ {
+ case CLASS_DRUID:
+ caster->CastSpell(caster, SPELL_SOUL_PRESERVER_DRUID, true, nullptr, aurEff);
+ break;
+ case CLASS_PALADIN:
+ caster->CastSpell(caster, SPELL_SOUL_PRESERVER_PALADIN, true, nullptr, aurEff);
+ break;
+ case CLASS_PRIEST:
+ caster->CastSpell(caster, SPELL_SOUL_PRESERVER_PRIEST, true, nullptr, aurEff);
+ break;
+ case CLASS_SHAMAN:
+ caster->CastSpell(caster, SPELL_SOUL_PRESERVER_SHAMAN, true, nullptr, aurEff);
+ break;
+ default:
+ break;
}
- };
+ }
- AuraScript* GetAuraScript() const override
+ void Register() override
{
- return new spell_item_soul_preserver_AuraScript();
+ OnEffectProc += AuraEffectProcFn(spell_item_soul_preserver::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
}
};
@@ -3916,40 +3176,29 @@ class spell_item_sunwell_neck : public SpellScriptLoader
}
};
-class spell_item_toy_train_set_pulse : public SpellScriptLoader
+class spell_item_toy_train_set_pulse : public SpellScript
{
-public:
- spell_item_toy_train_set_pulse() : SpellScriptLoader("spell_item_toy_train_set_pulse") { }
+ PrepareSpellScript(spell_item_toy_train_set_pulse);
- class spell_item_toy_train_set_pulse_SpellScript : public SpellScript
+ void HandleDummy(SpellEffIndex /*index*/)
{
- PrepareSpellScript(spell_item_toy_train_set_pulse_SpellScript);
-
- void HandleDummy(SpellEffIndex /*index*/)
+ if (Player* target = GetHitUnit()->ToPlayer())
{
- if (Player* target = GetHitUnit()->ToPlayer())
- {
- target->HandleEmoteCommand(EMOTE_ONESHOT_TRAIN);
- if (EmotesTextSoundEntry const* soundEntry = FindTextSoundEmoteFor(TEXT_EMOTE_TRAIN, target->getRace(), target->getGender()))
- target->PlayDistanceSound(soundEntry->SoundId);
- }
- }
-
- void HandleTargets(std::list<WorldObject*>& targetList)
- {
- targetList.remove_if([](WorldObject const* obj) { return obj->GetTypeId() != TYPEID_PLAYER; });
+ target->HandleEmoteCommand(EMOTE_ONESHOT_TRAIN);
+ if (EmotesTextSoundEntry const* soundEntry = FindTextSoundEmoteFor(TEXT_EMOTE_TRAIN, target->getRace(), target->getGender()))
+ target->PlayDistanceSound(soundEntry->SoundId);
}
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_toy_train_set_pulse_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_item_toy_train_set_pulse_SpellScript::HandleTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ALLY);
- }
- };
+ void HandleTargets(std::list<WorldObject*>& targetList)
+ {
+ targetList.remove_if([](WorldObject const* obj) { return obj->GetTypeId() != TYPEID_PLAYER; });
+ }
- SpellScript* GetSpellScript() const override
+ void Register() override
{
- return new spell_item_toy_train_set_pulse_SpellScript();
+ OnEffectHitTarget += SpellEffectFn(spell_item_toy_train_set_pulse::HandleDummy, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_item_toy_train_set_pulse::HandleTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ALLY);
}
};
@@ -3963,66 +3212,55 @@ enum DeathChoiceSpells
SPELL_DEATH_CHOICE_HEROIC_STRENGTH = 67773
};
-class spell_item_death_choice : public SpellScriptLoader
+class spell_item_death_choice : public AuraScript
{
-public:
- spell_item_death_choice() : SpellScriptLoader("spell_item_death_choice") { }
+ PrepareAuraScript(spell_item_death_choice);
- class spell_item_death_choice_AuraScript : public AuraScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
{
- PrepareAuraScript(spell_item_death_choice_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
+ return ValidateSpellInfo(
{
- return ValidateSpellInfo(
- {
- SPELL_DEATH_CHOICE_NORMAL_STRENGTH,
- SPELL_DEATH_CHOICE_NORMAL_AGILITY,
- SPELL_DEATH_CHOICE_HEROIC_STRENGTH,
- SPELL_DEATH_CHOICE_HEROIC_AGILITY
- });
- }
+ SPELL_DEATH_CHOICE_NORMAL_STRENGTH,
+ SPELL_DEATH_CHOICE_NORMAL_AGILITY,
+ SPELL_DEATH_CHOICE_HEROIC_STRENGTH,
+ SPELL_DEATH_CHOICE_HEROIC_AGILITY
+ });
+ }
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
- Unit* caster = eventInfo.GetActor();
- float str = caster->GetStat(STAT_STRENGTH);
- float agi = caster->GetStat(STAT_AGILITY);
+ Unit* caster = eventInfo.GetActor();
+ float str = caster->GetStat(STAT_STRENGTH);
+ float agi = caster->GetStat(STAT_AGILITY);
- switch (aurEff->GetId())
+ switch (aurEff->GetId())
+ {
+ case SPELL_DEATH_CHOICE_NORMAL_AURA:
{
- case SPELL_DEATH_CHOICE_NORMAL_AURA:
- {
- if (str > agi)
- caster->CastSpell(caster, SPELL_DEATH_CHOICE_NORMAL_STRENGTH, true, nullptr, aurEff);
- else
- caster->CastSpell(caster, SPELL_DEATH_CHOICE_NORMAL_AGILITY, true, nullptr, aurEff);
- break;
- }
- case SPELL_DEATH_CHOICE_HEROIC_AURA:
- {
- if (str > agi)
- caster->CastSpell(caster, SPELL_DEATH_CHOICE_HEROIC_STRENGTH, true, nullptr, aurEff);
- else
- caster->CastSpell(caster, SPELL_DEATH_CHOICE_HEROIC_AGILITY, true, nullptr, aurEff);
- break;
- }
- default:
- break;
+ if (str > agi)
+ caster->CastSpell(caster, SPELL_DEATH_CHOICE_NORMAL_STRENGTH, true, nullptr, aurEff);
+ else
+ caster->CastSpell(caster, SPELL_DEATH_CHOICE_NORMAL_AGILITY, true, nullptr, aurEff);
+ break;
}
+ case SPELL_DEATH_CHOICE_HEROIC_AURA:
+ {
+ if (str > agi)
+ caster->CastSpell(caster, SPELL_DEATH_CHOICE_HEROIC_STRENGTH, true, nullptr, aurEff);
+ else
+ caster->CastSpell(caster, SPELL_DEATH_CHOICE_HEROIC_AGILITY, true, nullptr, aurEff);
+ break;
+ }
+ default:
+ break;
}
+ }
- void Register() override
- {
- OnEffectProc += AuraEffectProcFn(spell_item_death_choice_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
- }
- };
-
- AuraScript* GetAuraScript() const override
+ void Register() override
{
- return new spell_item_death_choice_AuraScript();
+ OnEffectProc += AuraEffectProcFn(spell_item_death_choice::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
}
};
@@ -4113,75 +3351,64 @@ enum DarkmoonCardSpells
SPELL_DARKMOON_CARD_SPIRIT = 60235,
};
-class spell_item_darkmoon_card_greatness : public SpellScriptLoader
+class spell_item_darkmoon_card_greatness : public AuraScript
{
-public:
- spell_item_darkmoon_card_greatness() : SpellScriptLoader("spell_item_darkmoon_card_greatness") { }
+ PrepareAuraScript(spell_item_darkmoon_card_greatness);
- class spell_item_darkmoon_card_greatness_AuraScript : public AuraScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
{
- PrepareAuraScript(spell_item_darkmoon_card_greatness_AuraScript);
+ return ValidateSpellInfo(
+ {
+ SPELL_DARKMOON_CARD_STRENGTH,
+ SPELL_DARKMOON_CARD_AGILITY,
+ SPELL_DARKMOON_CARD_INTELLECT,
+ SPELL_DARKMOON_CARD_SPIRIT
+ });
+ }
- bool Validate(SpellInfo const* /*spellInfo*/) override
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+
+ Unit* caster = eventInfo.GetActor();
+ float str = caster->GetStat(STAT_STRENGTH);
+ float agi = caster->GetStat(STAT_AGILITY);
+ float intl = caster->GetStat(STAT_INTELLECT);
+ float spi = caster->GetStat(STAT_SPIRIT);
+ float stat = 0.0f;
+
+ uint32 spellTrigger = SPELL_DARKMOON_CARD_STRENGTH;
+
+ if (str > stat)
{
- return ValidateSpellInfo(
- {
- SPELL_DARKMOON_CARD_STRENGTH,
- SPELL_DARKMOON_CARD_AGILITY,
- SPELL_DARKMOON_CARD_INTELLECT,
- SPELL_DARKMOON_CARD_SPIRIT
- });
+ spellTrigger = SPELL_DARKMOON_CARD_STRENGTH;
+ stat = str;
}
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ if (agi > stat)
{
- PreventDefaultAction();
+ spellTrigger = SPELL_DARKMOON_CARD_AGILITY;
+ stat = agi;
+ }
- Unit* caster = eventInfo.GetActor();
- float str = caster->GetStat(STAT_STRENGTH);
- float agi = caster->GetStat(STAT_AGILITY);
- float intl = caster->GetStat(STAT_INTELLECT);
- float spi = caster->GetStat(STAT_SPIRIT);
- float stat = 0.0f;
-
- uint32 spellTrigger = SPELL_DARKMOON_CARD_STRENGTH;
-
- if (str > stat)
- {
- spellTrigger = SPELL_DARKMOON_CARD_STRENGTH;
- stat = str;
- }
-
- if (agi > stat)
- {
- spellTrigger = SPELL_DARKMOON_CARD_AGILITY;
- stat = agi;
- }
-
- if (intl > stat)
- {
- spellTrigger = SPELL_DARKMOON_CARD_INTELLECT;
- stat = intl;
- }
-
- if (spi > stat)
- {
- spellTrigger = SPELL_DARKMOON_CARD_SPIRIT;
- stat = spi;
- }
-
- caster->CastSpell(caster, spellTrigger, true, nullptr, aurEff);
+ if (intl > stat)
+ {
+ spellTrigger = SPELL_DARKMOON_CARD_INTELLECT;
+ stat = intl;
}
- void Register() override
+ if (spi > stat)
{
- OnEffectProc += AuraEffectProcFn(spell_item_darkmoon_card_greatness_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
+ spellTrigger = SPELL_DARKMOON_CARD_SPIRIT;
+ stat = spi;
}
- };
- AuraScript* GetAuraScript() const override
+ caster->CastSpell(caster, spellTrigger, true, nullptr, aurEff);
+ }
+
+ void Register() override
{
- return new spell_item_darkmoon_card_greatness_AuraScript();
+ OnEffectProc += AuraEffectProcFn(spell_item_darkmoon_card_greatness::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
}
};
@@ -4191,43 +3418,32 @@ enum CharmWitchDoctor
SPELL_CHARM_WITCH_DOCTOR_PROC = 43821
};
-class spell_item_charm_witch_doctor : public SpellScriptLoader
+class spell_item_charm_witch_doctor : public AuraScript
{
-public:
- spell_item_charm_witch_doctor() : SpellScriptLoader("spell_item_charm_witch_doctor") { }
+ PrepareAuraScript(spell_item_charm_witch_doctor);
- class spell_item_charm_witch_doctor_AuraScript : public AuraScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
{
- PrepareAuraScript(spell_item_charm_witch_doctor_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_CHARM_WITCH_DOCTOR_PROC });
- }
-
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
+ return ValidateSpellInfo({ SPELL_CHARM_WITCH_DOCTOR_PROC });
+ }
- Unit* caster = eventInfo.GetActor();
- Unit* target = eventInfo.GetActionTarget();
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
- if (target)
- {
- int32 bp = CalculatePct(target->GetCreateHealth(),aurEff->GetSpellInfo()->Effects[1].CalcValue());
- caster->CastCustomSpell(target, SPELL_CHARM_WITCH_DOCTOR_PROC, &bp, nullptr, nullptr, true, nullptr, aurEff);
- }
- }
+ Unit* caster = eventInfo.GetActor();
+ Unit* target = eventInfo.GetActionTarget();
- void Register() override
+ if (target)
{
- OnEffectProc += AuraEffectProcFn(spell_item_charm_witch_doctor_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
+ int32 bp = CalculatePct(target->GetCreateHealth(),aurEff->GetSpellInfo()->Effects[1].CalcValue());
+ caster->CastCustomSpell(target, SPELL_CHARM_WITCH_DOCTOR_PROC, &bp, nullptr, nullptr, true, nullptr, aurEff);
}
- };
+ }
- AuraScript* GetAuraScript() const override
+ void Register() override
{
- return new spell_item_charm_witch_doctor_AuraScript();
+ OnEffectProc += AuraEffectProcFn(spell_item_charm_witch_doctor::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
}
};
@@ -4238,47 +3454,36 @@ enum ManaDrainSpells
SPELL_MANA_DRAIN_LEECH = 27526
};
-class spell_item_mana_drain : public SpellScriptLoader
+class spell_item_mana_drain : public AuraScript
{
-public:
- spell_item_mana_drain() : SpellScriptLoader("spell_item_mana_drain") { }
+ PrepareAuraScript(spell_item_mana_drain);
- class spell_item_mana_drain_AuraScript : public AuraScript
+ bool Validate(SpellInfo const* /*spellInfo*/) override
{
- PrepareAuraScript(spell_item_mana_drain_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo(
- {
- SPELL_MANA_DRAIN_ENERGIZE,
- SPELL_MANA_DRAIN_LEECH
- });
- }
-
- void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ return ValidateSpellInfo(
{
- PreventDefaultAction();
+ SPELL_MANA_DRAIN_ENERGIZE,
+ SPELL_MANA_DRAIN_LEECH
+ });
+ }
- Unit* caster = eventInfo.GetActor();
- Unit* target = eventInfo.GetActionTarget();
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
- if (caster->IsAlive())
- caster->CastSpell(caster, SPELL_MANA_DRAIN_ENERGIZE, true, nullptr, aurEff);
+ Unit* caster = eventInfo.GetActor();
+ Unit* target = eventInfo.GetActionTarget();
- if (target && target->IsAlive())
- caster->CastSpell(target, SPELL_MANA_DRAIN_LEECH, true, nullptr, aurEff);
- }
+ if (caster->IsAlive())
+ caster->CastSpell(caster, SPELL_MANA_DRAIN_ENERGIZE, true, nullptr, aurEff);
- void Register() override
- {
- OnEffectProc += AuraEffectProcFn(spell_item_mana_drain_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
- }
- };
+ if (target && target->IsAlive())
+ caster->CastSpell(target, SPELL_MANA_DRAIN_LEECH, true, nullptr, aurEff);
+ }
- AuraScript* GetAuraScript() const override
+ void Register() override
{
- return new spell_item_mana_drain_AuraScript();
+ OnEffectProc += AuraEffectProcFn(spell_item_mana_drain::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
}
};
@@ -4290,57 +3495,46 @@ enum TauntFlag
};
// 51640 - Taunt Flag Targeting
-class spell_item_taunt_flag_targeting : public SpellScriptLoader
+class spell_item_taunt_flag_targeting : public SpellScript
{
- public:
- spell_item_taunt_flag_targeting() : SpellScriptLoader("spell_item_taunt_flag_targeting") { }
+ PrepareSpellScript(spell_item_taunt_flag_targeting);
- class spell_item_taunt_flag_targeting_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_taunt_flag_targeting_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_TAUNT_FLAG }) &&
- sObjectMgr->GetBroadcastText(EMOTE_PLANTS_FLAG);
- }
-
- void FilterTargets(std::list<WorldObject*>& targets)
- {
- targets.remove_if([](WorldObject* obj) -> bool
- {
- return obj->GetTypeId() != TYPEID_PLAYER && obj->GetTypeId() != TYPEID_CORPSE;
- });
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_TAUNT_FLAG }) &&
+ sObjectMgr->GetBroadcastText(EMOTE_PLANTS_FLAG);
+ }
- if (targets.empty())
- {
- FinishCast(SPELL_FAILED_NO_VALID_TARGETS);
- return;
- }
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ targets.remove_if([](WorldObject* obj) -> bool
+ {
+ return obj->GetTypeId() != TYPEID_PLAYER && obj->GetTypeId() != TYPEID_CORPSE;
+ });
- Trinity::Containers::RandomResize(targets, 1);
- }
+ if (targets.empty())
+ {
+ FinishCast(SPELL_FAILED_NO_VALID_TARGETS);
+ return;
+ }
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- // we *really* want the unit implementation here
- // it sends a packet like seen on sniff
- GetCaster()->Unit::TextEmote(EMOTE_PLANTS_FLAG, GetHitUnit(), false);
+ Trinity::Containers::RandomResize(targets, 1);
+ }
- GetCaster()->CastSpell(GetHitUnit(), SPELL_TAUNT_FLAG, true);
- }
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ // we *really* want the unit implementation here
+ // it sends a packet like seen on sniff
+ GetCaster()->Unit::TextEmote(EMOTE_PLANTS_FLAG, GetHitUnit(), false);
- void Register() override
- {
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_item_taunt_flag_targeting_SpellScript::FilterTargets, EFFECT_0, TARGET_CORPSE_SRC_AREA_ENEMY);
- OnEffectHitTarget += SpellEffectFn(spell_item_taunt_flag_targeting_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ GetCaster()->CastSpell(GetHitUnit(), SPELL_TAUNT_FLAG, true);
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_item_taunt_flag_targeting_SpellScript();
- }
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_item_taunt_flag_targeting::FilterTargets, EFFECT_0, TARGET_CORPSE_SRC_AREA_ENEMY);
+ OnEffectHitTarget += SpellEffectFn(spell_item_taunt_flag_targeting::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
// 13180 - Gnomish Mind Control Cap
@@ -4352,49 +3546,38 @@ enum MindControlCap
SPELL_DULLARD = 67809
};
-class spell_item_mind_control_cap : public SpellScriptLoader
+class spell_item_mind_control_cap : public SpellScript
{
- public:
- spell_item_mind_control_cap() : SpellScriptLoader("spell_item_mind_control_cap") { }
-
- class spell_item_mind_control_cap_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_mind_control_cap_SpellScript);
-
- bool Load() override
- {
- if (!GetCastItem())
- return false;
- return true;
- }
-
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo({ SPELL_GNOMISH_MIND_CONTROL_CAP, SPELL_DULLARD });
- }
+ PrepareSpellScript(spell_item_mind_control_cap);
- void HandleDummy(SpellEffIndex /* effIndex */)
- {
- Unit* caster = GetCaster();
- if (Unit* target = GetHitUnit())
- {
- if (roll_chance_i(ROLL_CHANCE_NO_BACKFIRE))
- caster->CastSpell(target, roll_chance_i(ROLL_CHANCE_DULLARD) ? SPELL_DULLARD : SPELL_GNOMISH_MIND_CONTROL_CAP, true, GetCastItem());
- else
- target->CastSpell(caster, SPELL_GNOMISH_MIND_CONTROL_CAP, true); // backfire - 5% chance
- }
- }
+ bool Load() override
+ {
+ if (!GetCastItem())
+ return false;
+ return true;
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_mind_control_cap_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_GNOMISH_MIND_CONTROL_CAP, SPELL_DULLARD });
+ }
- SpellScript* GetSpellScript() const override
+ void HandleDummy(SpellEffIndex /* effIndex */)
+ {
+ Unit* caster = GetCaster();
+ if (Unit* target = GetHitUnit())
{
- return new spell_item_mind_control_cap_SpellScript();
+ if (roll_chance_i(ROLL_CHANCE_NO_BACKFIRE))
+ caster->CastSpell(target, roll_chance_i(ROLL_CHANCE_DULLARD) ? SPELL_DULLARD : SPELL_GNOMISH_MIND_CONTROL_CAP, true, GetCastItem());
+ else
+ target->CastSpell(caster, SPELL_GNOMISH_MIND_CONTROL_CAP, true); // backfire - 5% chance
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_mind_control_cap::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
// 8344 - Universal Remote (Gnomish Universal Remote)
@@ -4405,51 +3588,40 @@ enum UniversalRemote
SPELL_TARGET_LOCK = 8347
};
-class spell_item_universal_remote : public SpellScriptLoader
+class spell_item_universal_remote : public SpellScript
{
- public:
- spell_item_universal_remote() : SpellScriptLoader("spell_item_universal_remote") { }
-
- class spell_item_universal_remote_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_item_universal_remote_SpellScript);
-
- bool Load() override
- {
- if (!GetCastItem())
- return false;
- return true;
- }
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_CONTROL_MACHINE, SPELL_MOBILITY_MALFUNCTION, SPELL_TARGET_LOCK });
- }
+ PrepareSpellScript(spell_item_universal_remote);
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- if (Unit* target = GetHitUnit())
- {
- uint8 chance = urand(0, 99);
- if (chance < 15)
- GetCaster()->CastSpell(target, SPELL_TARGET_LOCK, true, GetCastItem());
- else if (chance < 25)
- GetCaster()->CastSpell(target, SPELL_MOBILITY_MALFUNCTION, true, GetCastItem());
- else
- GetCaster()->CastSpell(target, SPELL_CONTROL_MACHINE, true, GetCastItem());
- }
- }
+ bool Load() override
+ {
+ if (!GetCastItem())
+ return false;
+ return true;
+ }
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_item_universal_remote_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_CONTROL_MACHINE, SPELL_MOBILITY_MALFUNCTION, SPELL_TARGET_LOCK });
+ }
- SpellScript* GetSpellScript() const override
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
{
- return new spell_item_universal_remote_SpellScript();
+ uint8 chance = urand(0, 99);
+ if (chance < 15)
+ GetCaster()->CastSpell(target, SPELL_TARGET_LOCK, true, GetCastItem());
+ else if (chance < 25)
+ GetCaster()->CastSpell(target, SPELL_MOBILITY_MALFUNCTION, true, GetCastItem());
+ else
+ GetCaster()->CastSpell(target, SPELL_CONTROL_MACHINE, true, GetCastItem());
}
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_universal_remote::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
enum ZandalarianCharms
@@ -4514,137 +3686,113 @@ class spell_item_zandalarian_charm : public SpellScriptLoader
};
// 45051 - Mad Alchemist's Potion (34440)
-class spell_item_mad_alchemists_potion : public SpellScriptLoader
+class spell_item_mad_alchemists_potion : public SpellScript
{
-public:
- spell_item_mad_alchemists_potion() : SpellScriptLoader("spell_item_mad_alchemists_potion") {}
+ PrepareSpellScript(spell_item_mad_alchemists_potion);
- class mad_alchemists_potion_SpellScript : public SpellScript
+ void SecondaryEffect()
{
- PrepareSpellScript(mad_alchemists_potion_SpellScript);
-
- void SecondaryEffect()
- {
- std::vector<uint32> availableElixirs =
- {
- // Battle Elixirs
- 33720, // Onslaught Elixir (28102)
- 54452, // Adept's Elixir (28103)
- 33726, // Elixir of Mastery (28104)
- 28490, // Elixir of Major Strength (22824)
- 28491, // Elixir of Healing Power (22825)
- 28493, // Elixir of Major Frost Power (22827)
- 54494, // Elixir of Major Agility (22831)
- 28501, // Elixir of Major Firepower (22833)
- 28503,// Elixir of Major Shadow Power (22835)
- 38954, // Fel Strength Elixir (31679)
- // Guardian Elixirs
- 39625, // Elixir of Major Fortitude (32062)
- 39626, // Earthen Elixir (32063)
- 39627, // Elixir of Draenic Wisdom (32067)
- 39628, // Elixir of Ironskin (32068)
- 28502, // Elixir of Major Defense (22834)
- 28514, // Elixir of Empowerment (22848)
- // Other
- 28489, // Elixir of Camouflage (22823)
- 28496 // Elixir of the Searching Eye (22830)
- };
-
- Unit* target = GetCaster();
-
- if (target->getPowerType() == POWER_MANA)
- availableElixirs.push_back(28509); // Elixir of Major Mageblood (22840)
-
- uint32 chosenElixir = Trinity::Containers::SelectRandomContainerElement(availableElixirs);
-
- bool useElixir = true;
-
- SpellGroup chosenSpellGroup = SPELL_GROUP_NONE;
- if (sSpellMgr->IsSpellMemberOfSpellGroup(chosenElixir, SPELL_GROUP_ELIXIR_BATTLE))
- chosenSpellGroup = SPELL_GROUP_ELIXIR_BATTLE;
- if (sSpellMgr->IsSpellMemberOfSpellGroup(chosenElixir, SPELL_GROUP_ELIXIR_GUARDIAN))
- chosenSpellGroup = SPELL_GROUP_ELIXIR_GUARDIAN;
- // If another spell of the same group is already active the elixir should not be cast
- if (chosenSpellGroup != SPELL_GROUP_NONE)
- {
- Unit::AuraApplicationMap const& auraMap = target->GetAppliedAuras();
- for (auto itr = auraMap.begin(); itr != auraMap.end(); ++itr)
+ std::vector<uint32> availableElixirs =
+ {
+ // Battle Elixirs
+ 33720, // Onslaught Elixir (28102)
+ 54452, // Adept's Elixir (28103)
+ 33726, // Elixir of Mastery (28104)
+ 28490, // Elixir of Major Strength (22824)
+ 28491, // Elixir of Healing Power (22825)
+ 28493, // Elixir of Major Frost Power (22827)
+ 54494, // Elixir of Major Agility (22831)
+ 28501, // Elixir of Major Firepower (22833)
+ 28503,// Elixir of Major Shadow Power (22835)
+ 38954, // Fel Strength Elixir (31679)
+ // Guardian Elixirs
+ 39625, // Elixir of Major Fortitude (32062)
+ 39626, // Earthen Elixir (32063)
+ 39627, // Elixir of Draenic Wisdom (32067)
+ 39628, // Elixir of Ironskin (32068)
+ 28502, // Elixir of Major Defense (22834)
+ 28514, // Elixir of Empowerment (22848)
+ // Other
+ 28489, // Elixir of Camouflage (22823)
+ 28496 // Elixir of the Searching Eye (22830)
+ };
+
+ Unit* target = GetCaster();
+
+ if (target->getPowerType() == POWER_MANA)
+ availableElixirs.push_back(28509); // Elixir of Major Mageblood (22840)
+
+ uint32 chosenElixir = Trinity::Containers::SelectRandomContainerElement(availableElixirs);
+
+ bool useElixir = true;
+
+ SpellGroup chosenSpellGroup = SPELL_GROUP_NONE;
+ if (sSpellMgr->IsSpellMemberOfSpellGroup(chosenElixir, SPELL_GROUP_ELIXIR_BATTLE))
+ chosenSpellGroup = SPELL_GROUP_ELIXIR_BATTLE;
+ if (sSpellMgr->IsSpellMemberOfSpellGroup(chosenElixir, SPELL_GROUP_ELIXIR_GUARDIAN))
+ chosenSpellGroup = SPELL_GROUP_ELIXIR_GUARDIAN;
+ // If another spell of the same group is already active the elixir should not be cast
+ if (chosenSpellGroup != SPELL_GROUP_NONE)
+ {
+ Unit::AuraApplicationMap const& auraMap = target->GetAppliedAuras();
+ for (auto itr = auraMap.begin(); itr != auraMap.end(); ++itr)
+ {
+ uint32 spellId = itr->second->GetBase()->GetId();
+ if (sSpellMgr->IsSpellMemberOfSpellGroup(spellId, chosenSpellGroup) && spellId != chosenElixir)
{
- uint32 spellId = itr->second->GetBase()->GetId();
- if (sSpellMgr->IsSpellMemberOfSpellGroup(spellId, chosenSpellGroup) && spellId != chosenElixir)
- {
- useElixir = false;
- break;
- }
+ useElixir = false;
+ break;
}
}
-
- if (useElixir)
- target->CastSpell(target, chosenElixir, true, GetCastItem());
- }
-
- void Register() override
- {
- AfterCast += SpellCastFn(mad_alchemists_potion_SpellScript::SecondaryEffect);
}
- };
+ if (useElixir)
+ target->CastSpell(target, chosenElixir, true, GetCastItem());
+ }
- SpellScript* GetSpellScript() const override
+ void Register() override
{
- return new mad_alchemists_potion_SpellScript();
+ AfterCast += SpellCastFn(spell_item_mad_alchemists_potion::SecondaryEffect);
}
};
// 53750 - Crazy Alchemist's Potion (40077)
-class spell_item_crazy_alchemists_potion : public SpellScriptLoader
+class spell_item_crazy_alchemists_potion : public SpellScript
{
-public:
- spell_item_crazy_alchemists_potion() : SpellScriptLoader("spell_item_crazy_alchemists_potion") {}
+ PrepareSpellScript(spell_item_crazy_alchemists_potion);
- class crazy_alchemists_potion_SpellScript : public SpellScript
+ void SecondaryEffect()
{
- PrepareSpellScript(crazy_alchemists_potion_SpellScript);
-
- void SecondaryEffect()
+ std::vector<uint32> availableElixirs =
{
- std::vector<uint32> availableElixirs =
- {
- 43185, // Runic Healing Potion (33447)
- 53750, // Crazy Alchemist's Potion (40077)
- 53761, // Powerful Rejuvenation Potion (40087)
- 53762, // Indestructible Potion (40093)
- 53908, // Potion of Speed (40211)
- 53909, // Potion of Wild Magic (40212)
- 53910, // Mighty Arcane Protection Potion (40213)
- 53911, // Mighty Fire Protection Potion (40214)
- 53913, // Mighty Frost Protection Potion (40215)
- 53914, // Mighty Nature Protection Potion (40216)
- 53915 // Mighty Shadow Protection Potion (40217)
- };
-
- Unit* target = GetCaster();
-
- if (!target->IsInCombat())
- availableElixirs.push_back(53753); // Potion of Nightmares (40081)
- if (target->getPowerType() == POWER_MANA)
- availableElixirs.push_back(43186); // Runic Mana Potion(33448)
-
- uint32 chosenElixir = Trinity::Containers::SelectRandomContainerElement(availableElixirs);
+ 43185, // Runic Healing Potion (33447)
+ 53750, // Crazy Alchemist's Potion (40077)
+ 53761, // Powerful Rejuvenation Potion (40087)
+ 53762, // Indestructible Potion (40093)
+ 53908, // Potion of Speed (40211)
+ 53909, // Potion of Wild Magic (40212)
+ 53910, // Mighty Arcane Protection Potion (40213)
+ 53911, // Mighty Fire Protection Potion (40214)
+ 53913, // Mighty Frost Protection Potion (40215)
+ 53914, // Mighty Nature Protection Potion (40216)
+ 53915 // Mighty Shadow Protection Potion (40217)
+ };
- target->CastSpell(target, chosenElixir, true, GetCastItem());
- }
+ Unit* target = GetCaster();
- void Register() override
- {
- AfterCast += SpellCastFn(crazy_alchemists_potion_SpellScript::SecondaryEffect);
- }
+ if (!target->IsInCombat())
+ availableElixirs.push_back(53753); // Potion of Nightmares (40081)
+ if (target->getPowerType() == POWER_MANA)
+ availableElixirs.push_back(43186); // Runic Mana Potion(33448)
- };
+ uint32 chosenElixir = Trinity::Containers::SelectRandomContainerElement(availableElixirs);
+
+ target->CastSpell(target, chosenElixir, true, GetCastItem());
+ }
- SpellScript* GetSpellScript() const override
+ void Register() override
{
- return new crazy_alchemists_potion_SpellScript();
+ AfterCast += SpellCastFn(spell_item_crazy_alchemists_potion::SecondaryEffect);
}
};
@@ -4659,110 +3807,111 @@ void AddSC_item_spell_scripts()
// 23075 Mithril Mechanical Dragonling
new spell_item_trigger_spell("spell_item_mithril_mechanical_dragonling", SPELL_MITHRIL_MECHANICAL_DRAGONLING);
- new spell_item_aegis_of_preservation();
- new spell_item_arcane_shroud();
- new spell_item_alchemists_stone();
+ RegisterAuraScript(spell_item_aegis_of_preservation);
+ RegisterAuraScript(spell_item_alchemists_stone);
new spell_item_anger_capacitor<8>("spell_item_tiny_abomination_in_a_jar");
new spell_item_anger_capacitor<7>("spell_item_tiny_abomination_in_a_jar_hero");
- new spell_item_aura_of_madness();
- new spell_item_dementia();
- new spell_item_blessing_of_ancient_kings();
- new spell_item_deadly_precision();
- new spell_item_deadly_precision_dummy();
+ RegisterAuraScript(spell_item_arcane_shroud);
+ RegisterAuraScript(spell_item_aura_of_madness);
+ RegisterAuraScript(spell_item_dementia);
+ RegisterAuraScript(spell_item_blessing_of_ancient_kings);
+ RegisterAuraScript(spell_item_deadly_precision);
+ RegisterSpellScript(spell_item_deadly_precision_dummy);
new spell_item_deathbringers_will<SPELL_STRENGTH_OF_THE_TAUNKA, SPELL_AGILITY_OF_THE_VRYKUL, SPELL_POWER_OF_THE_TAUNKA, SPELL_AIM_OF_THE_IRON_DWARVES, SPELL_SPEED_OF_THE_VRYKUL>("spell_item_deathbringers_will_normal");
new spell_item_deathbringers_will<SPELL_STRENGTH_OF_THE_TAUNKA_HERO, SPELL_AGILITY_OF_THE_VRYKUL_HERO, SPELL_POWER_OF_THE_TAUNKA_HERO, SPELL_AIM_OF_THE_IRON_DWARVES_HERO, SPELL_SPEED_OF_THE_VRYKUL_HERO>("spell_item_deathbringers_will_heroic");
- new spell_item_decahedral_dwarven_dice();
+ RegisterSpellScript(spell_item_decahedral_dwarven_dice);
new spell_item_defibrillate("spell_item_goblin_jumper_cables", 67, SPELL_GOBLIN_JUMPER_CABLES_FAIL);
new spell_item_defibrillate("spell_item_goblin_jumper_cables_xl", 50, SPELL_GOBLIN_JUMPER_CABLES_XL_FAIL);
new spell_item_defibrillate("spell_item_gnomish_army_knife", 33);
- new spell_item_desperate_defense();
- new spell_item_deviate_fish();
- new spell_item_discerning_eye_beast_dummy();
- new spell_item_echoes_of_light();
- new spell_item_fate_rune_of_unsurpassed_vigor();
- new spell_item_flask_of_the_north();
- new spell_item_frozen_shadoweave();
- new spell_item_gnomish_death_ray();
- new spell_item_harm_prevention_belt();
- new spell_item_healing_touch_refund();
+ RegisterAuraScript(spell_item_desperate_defense);
+ RegisterSpellScript(spell_item_deviate_fish);
+ RegisterAuraScript(spell_item_discerning_eye_beast_dummy);
+ RegisterSpellScript(spell_item_echoes_of_light);
+ RegisterAuraScript(spell_item_fate_rune_of_unsurpassed_vigor);
+ RegisterSpellScript(spell_item_flask_of_the_north);
+ RegisterAuraScript(spell_item_frozen_shadoweave);
+ RegisterSpellScript(spell_item_gnomish_death_ray);
+ RegisterAuraScript(spell_item_harm_prevention_belt);
+ RegisterAuraScript(spell_item_healing_touch_refund);
new spell_item_heartpierce<SPELL_INVIGORATION_ENERGY, SPELL_INVIGORATION_MANA, SPELL_INVIGORATION_RAGE, SPELL_INVIGORATION_RP>("spell_item_heartpierce");
new spell_item_heartpierce<SPELL_INVIGORATION_ENERGY_HERO, SPELL_INVIGORATION_MANA_HERO, SPELL_INVIGORATION_RAGE_HERO, SPELL_INVIGORATION_RP_HERO>("spell_item_heartpierce_hero");
- new spell_item_crystal_spire_of_karabor();
- new spell_item_make_a_wish();
- new spell_item_mark_of_conquest();
- new spell_item_mingos_fortune_generator();
- new spell_item_necrotic_touch();
- new spell_item_net_o_matic();
- new spell_item_noggenfogger_elixir();
- new spell_item_pendant_of_the_violet_eye();
- new spell_item_persistent_shield();
- new spell_item_pet_healing();
- new spell_item_piccolo_of_the_flaming_fire();
- new spell_item_savory_deviate_delight();
- new spell_item_scroll_of_recall();
- new spell_item_unsated_craving();
- new spell_item_shadows_fate();
- new spell_item_shadowmourne();
- new spell_item_shadowmourne_soul_fragment();
- new spell_item_six_demon_bag();
- new spell_item_swift_hand_justice_dummy();
- new spell_item_totem_of_flowing_water();
- new spell_item_the_eye_of_diminution();
- new spell_item_underbelly_elixir();
- new spell_item_worn_troll_dice();
- new spell_item_red_rider_air_rifle();
-
- new spell_item_create_heart_candy();
- new spell_item_book_of_glyph_mastery();
- new spell_item_gift_of_the_harvester();
- new spell_item_map_of_the_geyser_fields();
- new spell_item_vanquished_clutches();
-
- new spell_item_ashbringer();
- new spell_magic_eater_food();
- new spell_item_refocus();
- new spell_item_shimmering_vessel();
- new spell_item_purify_helboar_meat();
- new spell_item_crystal_prison_dummy_dnd();
- new spell_item_reindeer_transformation();
- new spell_item_nigh_invulnerability();
- new spell_item_poultryizer();
- new spell_item_socrethars_stone();
- new spell_item_demon_broiled_surprise();
- new spell_item_complete_raptor_capture();
- new spell_item_impale_leviroth();
- new spell_item_brewfest_mount_transformation();
- new spell_item_nitro_boots();
- new spell_item_teach_language();
- new spell_item_rocket_boots();
- new spell_item_pygmy_oil();
- new spell_item_unusual_compass();
- new spell_item_chicken_cover();
- new spell_item_muisek_vessel();
- new spell_item_greatmothers_soulcatcher();
+ RegisterAuraScript(spell_item_crystal_spire_of_karabor);
+ RegisterSpellScript(spell_item_make_a_wish);
+ RegisterAuraScript(spell_item_mark_of_conquest);
+ RegisterSpellScript(spell_item_mingos_fortune_generator);
+ RegisterAuraScript(spell_item_necrotic_touch);
+ RegisterSpellScript(spell_item_net_o_matic);
+ RegisterSpellScript(spell_item_noggenfogger_elixir);
+ RegisterAuraScript(spell_item_pendant_of_the_violet_eye);
+ RegisterAuraScript(spell_item_persistent_shield);
+ RegisterAuraScript(spell_item_pet_healing);
+ RegisterSpellScript(spell_item_piccolo_of_the_flaming_fire);
+ RegisterSpellScript(spell_item_savory_deviate_delight);
+ RegisterSpellScript(spell_item_scroll_of_recall);
+ RegisterAuraScript(spell_item_unsated_craving);
+ RegisterAuraScript(spell_item_shadows_fate);
+ RegisterAuraScript(spell_item_shadowmourne);
+ RegisterAuraScript(spell_item_shadowmourne_soul_fragment);
+ RegisterSpellScript(spell_item_six_demon_bag);
+ RegisterAuraScript(spell_item_swift_hand_justice_dummy);
+ RegisterAuraScript(spell_item_totem_of_flowing_water);
+ RegisterAuraScript(spell_item_the_eye_of_diminution);
+ RegisterSpellScript(spell_item_underbelly_elixir);
+ RegisterSpellScript(spell_item_worn_troll_dice);
+ RegisterSpellScript(spell_item_red_rider_air_rifle);
+
+ RegisterSpellScript(spell_item_create_heart_candy);
+ RegisterSpellScript(spell_item_book_of_glyph_mastery);
+ RegisterSpellScript(spell_item_gift_of_the_harvester);
+ RegisterSpellScript(spell_item_map_of_the_geyser_fields);
+ RegisterSpellScript(spell_item_vanquished_clutches);
+
+ RegisterSpellScript(spell_item_ashbringer);
+ RegisterAuraScript(spell_magic_eater_food);
+ RegisterSpellScript(spell_item_shimmering_vessel);
+ RegisterSpellScript(spell_item_purify_helboar_meat);
+ RegisterSpellScript(spell_item_crystal_prison_dummy_dnd);
+ RegisterSpellScript(spell_item_reindeer_transformation);
+ RegisterSpellScript(spell_item_nigh_invulnerability);
+ RegisterSpellScript(spell_item_poultryizer);
+ RegisterSpellScript(spell_item_socrethars_stone);
+ RegisterSpellScript(spell_item_demon_broiled_surprise);
+ RegisterSpellScript(spell_item_complete_raptor_capture);
+ RegisterSpellScript(spell_item_impale_leviroth);
+ RegisterSpellScript(spell_item_brewfest_mount_transformation);
+ RegisterSpellScript(spell_item_nitro_boosts);
+ RegisterAuraScript(spell_item_nitro_boosts_backfire);
+ RegisterSpellScript(spell_item_teach_language);
+ RegisterSpellScript(spell_item_rocket_boots);
+ RegisterSpellScript(spell_item_pygmy_oil);
+ RegisterSpellScript(spell_item_unusual_compass);
+ RegisterSpellScript(spell_item_chicken_cover);
+ RegisterSpellScript(spell_item_refocus);
+ RegisterSpellScript(spell_item_muisek_vessel);
+ RegisterSpellScript(spell_item_greatmothers_soulcatcher);
new spell_item_shard_of_the_scale<SPELL_PURIFIED_CAUTERIZING_HEAL, SPELL_PURIFIED_SEARING_FLAMES>("spell_item_purified_shard_of_the_scale");
new spell_item_shard_of_the_scale<SPELL_SHINY_CAUTERIZING_HEAL, SPELL_SHINY_SEARING_FLAMES>("spell_item_shiny_shard_of_the_scale");
- new spell_item_soul_preserver();
+ RegisterAuraScript(spell_item_soul_preserver);
new spell_item_sunwell_neck<SPELL_LIGHTS_WRATH, SPELL_ARCANE_BOLT>("spell_item_sunwell_exalted_caster_neck");
new spell_item_sunwell_neck<SPELL_LIGHTS_STRENGTH, SPELL_ARCANE_STRIKE>("spell_item_sunwell_exalted_melee_neck");
new spell_item_sunwell_neck<SPELL_LIGHTS_WARD, SPELL_ARCANE_INSIGHT>("spell_item_sunwell_exalted_tank_neck");
new spell_item_sunwell_neck<SPELL_LIGHTS_SALVATION, SPELL_ARCANE_SURGE>("spell_item_sunwell_exalted_healer_neck");
- new spell_item_toy_train_set_pulse();
- new spell_item_death_choice();
+ RegisterSpellScript(spell_item_toy_train_set_pulse);
+ RegisterAuraScript(spell_item_death_choice);
new spell_item_trinket_stack("spell_item_lightning_capacitor", SPELL_LIGHTNING_CAPACITOR_STACK, SPELL_LIGHTNING_CAPACITOR_TRIGGER);
new spell_item_trinket_stack("spell_item_thunder_capacitor", SPELL_THUNDER_CAPACITOR_STACK, SPELL_THUNDER_CAPACITOR_TRIGGER);
new spell_item_trinket_stack("spell_item_toc25_normal_caster_trinket", SPELL_TOC25_CASTER_TRINKET_NORMAL_STACK, SPELL_TOC25_CASTER_TRINKET_NORMAL_TRIGGER);
new spell_item_trinket_stack("spell_item_toc25_heroic_caster_trinket", SPELL_TOC25_CASTER_TRINKET_HEROIC_STACK, SPELL_TOC25_CASTER_TRINKET_HEROIC_TRIGGER);
- new spell_item_darkmoon_card_greatness();
- new spell_item_charm_witch_doctor();
- new spell_item_mana_drain();
- new spell_item_taunt_flag_targeting();
- new spell_item_mind_control_cap();
- new spell_item_universal_remote();
+ RegisterAuraScript(spell_item_darkmoon_card_greatness);
+ RegisterAuraScript(spell_item_charm_witch_doctor);
+ RegisterAuraScript(spell_item_mana_drain);
+ RegisterSpellScript(spell_item_taunt_flag_targeting);
+ RegisterSpellScript(spell_item_mind_control_cap);
+ RegisterSpellScript(spell_item_universal_remote);
new spell_item_zandalarian_charm("spell_item_unstable_power", SPELL_UNSTABLE_POWER_AURA_STACK);
new spell_item_zandalarian_charm("spell_item_restless_strength", SPELL_RESTLESS_STRENGTH_AURA_STACK);
- new spell_item_mad_alchemists_potion();
- new spell_item_crazy_alchemists_potion();
+ RegisterSpellScript(spell_item_mad_alchemists_potion);
+ RegisterSpellScript(spell_item_crazy_alchemists_potion);
}
diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp
index 440c0ba4c5e..e45ed806ec2 100644
--- a/src/server/scripts/Spells/spell_mage.cpp
+++ b/src/server/scripts/Spells/spell_mage.cpp
@@ -74,7 +74,8 @@ enum MageSpellIcons
{
SPELL_ICON_MAGE_SHATTERED_BARRIER = 2945,
SPELL_ICON_MAGE_PRESENCE_OF_MIND = 139,
- SPELL_ICON_MAGE_CLEARCASTING = 212
+ SPELL_ICON_MAGE_CLEARCASTING = 212,
+ SPELL_ICON_MAGE_LIVING_BOMB = 3000
};
// Incanter's Absorbtion
@@ -357,7 +358,7 @@ class spell_mage_combustion : public SpellScriptLoader
// Do not take charges, add a stack of crit buff
if (!(eventInfo.GetHitMask() & PROC_HIT_CRITICAL))
{
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_MAGE_COMBUSTION_PROC, true);
+ eventInfo.GetActor()->CastSpell(nullptr, SPELL_MAGE_COMBUSTION_PROC, true);
return false;
}
@@ -408,6 +409,26 @@ class spell_mage_combustion_proc : public SpellScriptLoader
}
};
+// -31661 - Dragon's Breath
+class spell_mage_dragon_breath : public AuraScript
+{
+ PrepareAuraScript(spell_mage_dragon_breath);
+
+ bool CheckProc(ProcEventInfo& eventInfo)
+ {
+ // Dont proc with Living Bomb explosion
+ SpellInfo const* spellInfo = eventInfo.GetSpellInfo();
+ if (spellInfo && spellInfo->SpellIconID == SPELL_ICON_MAGE_LIVING_BOMB && spellInfo->SpellFamilyName == SPELLFAMILY_MAGE)
+ return false;
+ return true;
+ }
+
+ void Register() override
+ {
+ DoCheckProc += AuraCheckProcFn(spell_mage_dragon_breath::CheckProc);
+ }
+};
+
// -11185 - Improved Blizzard
class spell_mage_imp_blizzard : public SpellScriptLoader
{
@@ -461,7 +482,7 @@ class spell_mage_imp_mana_gems : public SpellScriptLoader
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_MAGE_MANA_SURGE, true, nullptr, aurEff);
+ eventInfo.GetActor()->CastSpell(nullptr, SPELL_MAGE_MANA_SURGE, true, nullptr, aurEff);
}
void Register() override
@@ -712,7 +733,7 @@ class spell_mage_gen_extra_effects : public SpellScriptLoader
Unit* caster = eventInfo.GetActor();
if (caster->HasAura(SPELL_MAGE_T10_2P_BONUS))
- caster->CastSpell((Unit*)nullptr, SPELL_MAGE_T10_2P_BONUS_EFFECT, true);
+ caster->CastSpell(nullptr, SPELL_MAGE_T10_2P_BONUS_EFFECT, true);
}
void Register() override
@@ -1295,6 +1316,7 @@ void AddSC_mage_spell_scripts()
new spell_mage_cold_snap();
new spell_mage_combustion();
new spell_mage_combustion_proc();
+ RegisterAuraScript(spell_mage_dragon_breath);
new spell_mage_imp_blizzard();
new spell_mage_imp_mana_gems();
new spell_mage_empowered_fire();
diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp
index 08ea6472a8d..28455808c01 100644
--- a/src/server/scripts/Spells/spell_paladin.cpp
+++ b/src/server/scripts/Spells/spell_paladin.cpp
@@ -1631,8 +1631,8 @@ class spell_pal_judgements_of_the_wise : public SpellScriptLoader
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
- caster->CastSpell((Unit*)nullptr, SPELL_PALADIN_JUDGEMENTS_OF_THE_WISE_MANA, true, nullptr, aurEff);
- caster->CastSpell((Unit*)nullptr, SPELL_REPLENISHMENT, true, nullptr, aurEff);
+ caster->CastSpell(nullptr, SPELL_PALADIN_JUDGEMENTS_OF_THE_WISE_MANA, true, nullptr, aurEff);
+ caster->CastSpell(nullptr, SPELL_REPLENISHMENT, true, nullptr, aurEff);
}
void Register() override
@@ -2223,7 +2223,7 @@ class spell_pal_sheath_of_light : public SpellScriptLoader
Unit* target = eventInfo.GetProcTarget();
SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_PALADIN_SHEATH_OF_LIGHT_HEAL);
- int32 amount = CalculatePct(static_cast<int32>(healInfo->GetHeal()), aurEff->GetAmount());
+ int32 amount = CalculatePct(static_cast<int32>(healInfo->GetEffectiveHeal()), aurEff->GetAmount());
amount /= spellInfo->GetMaxTicks();
// Add remaining ticks to healing done
amount += target->GetRemainingPeriodicAmount(caster->GetGUID(), SPELL_PALADIN_SHEATH_OF_LIGHT_HEAL, SPELL_AURA_PERIODIC_HEAL);
diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp
index 4ba231b021c..74c728a6cb0 100644
--- a/src/server/scripts/Spells/spell_priest.cpp
+++ b/src/server/scripts/Spells/spell_priest.cpp
@@ -648,10 +648,10 @@ class spell_pri_item_t6_trinket : public SpellScriptLoader
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
if (eventInfo.GetSpellTypeMask() & PROC_SPELL_TYPE_HEAL)
- caster->CastSpell((Unit*)nullptr, SPELL_PRIEST_DIVINE_BLESSING, true, nullptr, aurEff);
+ caster->CastSpell(nullptr, SPELL_PRIEST_DIVINE_BLESSING, true, nullptr, aurEff);
if (eventInfo.GetSpellTypeMask() & PROC_SPELL_TYPE_DAMAGE)
- caster->CastSpell((Unit*)nullptr, SPELL_PRIEST_DIVINE_WRATH, true, nullptr, aurEff);
+ caster->CastSpell(nullptr, SPELL_PRIEST_DIVINE_WRATH, true, nullptr, aurEff);
}
void Register() override
@@ -1287,7 +1287,7 @@ class spell_pri_vampiric_touch : public SpellScriptLoader
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_REPLENISHMENT, true, nullptr, aurEff);
+ eventInfo.GetActor()->CastSpell(nullptr, SPELL_REPLENISHMENT, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp
index e3ef1faee6f..7cc32340665 100644
--- a/src/server/scripts/Spells/spell_quest.cpp
+++ b/src/server/scripts/Spells/spell_quest.cpp
@@ -2149,7 +2149,7 @@ class spell_q12641_death_comes_from_on_high : public SpellScriptLoader
return;
}
- GetCaster()->CastSpell((Unit*)nullptr, spellId, true);
+ GetCaster()->CastSpell(nullptr, spellId, true);
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp
index 750b5073a7c..0476c4c09df 100644
--- a/src/server/scripts/Spells/spell_rogue.cpp
+++ b/src/server/scripts/Spells/spell_rogue.cpp
@@ -1022,7 +1022,7 @@ public:
return;
if (Player* player = caster->ToPlayer())
- player->CastSpell((Unit*)nullptr, SPELL_ROGUE_HONOR_AMONG_THIEVES_2, true);
+ player->CastSpell(nullptr, SPELL_ROGUE_HONOR_AMONG_THIEVES_2, true);
}
void Register() override
@@ -1060,7 +1060,7 @@ class spell_rog_turn_the_tables : public SpellScriptLoader
if (!caster)
return;
- caster->CastSpell((Unit*)nullptr, GetSpellInfo()->Effects[EFFECT_0].TriggerSpell, true, nullptr, aurEff);
+ caster->CastSpell(nullptr, GetSpellInfo()->Effects[EFFECT_0].TriggerSpell, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp
index 72208d73653..ecde34a4b8e 100644
--- a/src/server/scripts/Spells/spell_shaman.cpp
+++ b/src/server/scripts/Spells/spell_shaman.cpp
@@ -455,7 +455,7 @@ class spell_sha_earthbind_totem : public SpellScriptLoader
if (Player* owner = GetCaster()->GetCharmerOrOwnerPlayerOrPlayerItself())
if (AuraEffect* aur = owner->GetDummyAuraEffect(SPELLFAMILY_SHAMAN, 2289, 0))
if (roll_chance_i(aur->GetBaseAmount()))
- GetTarget()->CastSpell((Unit*)nullptr, SPELL_SHAMAN_TOTEM_EARTHEN_POWER, true);
+ GetTarget()->CastSpell(nullptr, SPELL_SHAMAN_TOTEM_EARTHEN_POWER, true);
}
void Apply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
@@ -1075,7 +1075,7 @@ class spell_sha_imp_water_shield : public SpellScriptLoader
return;
uint32 spellId = waterShield->GetSpellInfo()->Effects[waterShield->GetEffIndex()].TriggerSpell;
- caster->CastSpell((Unit*)nullptr, spellId, true, nullptr, aurEff);
+ caster->CastSpell(nullptr, spellId, true, nullptr, aurEff);
}
void Register() override
@@ -1308,7 +1308,7 @@ class spell_sha_item_t6_trinket : public SpellScriptLoader
return;
if (roll_chance_i(chance))
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, spellId, true, nullptr, aurEff);
+ eventInfo.GetActor()->CastSpell(nullptr, spellId, true, nullptr, aurEff);
}
void Register() override
@@ -1474,7 +1474,7 @@ class spell_sha_maelstrom_weapon : public SpellScriptLoader
if (!aurEff || !roll_chance_i(aurEff->GetAmount()))
return;
- caster->CastSpell((Unit*)nullptr, SPELL_SHAMAN_MAELSTROM_POWER, true, nullptr, aurEff);
+ caster->CastSpell(nullptr, SPELL_SHAMAN_MAELSTROM_POWER, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp
index 4ff38244435..3ee5f8f4e7c 100644
--- a/src/server/scripts/Spells/spell_warlock.cpp
+++ b/src/server/scripts/Spells/spell_warlock.cpp
@@ -1334,11 +1334,11 @@ class spell_warl_soul_leech : public SpellScriptLoader
uint32 selfSpellId = casterMana[impSoulLeechRank - 1];
uint32 petSpellId = petMana[impSoulLeechRank - 1];
- caster->CastSpell((Unit*)nullptr, selfSpellId, true, nullptr, aurEff);
- caster->CastSpell((Unit*)nullptr, petSpellId, true, nullptr, aurEff);
+ caster->CastSpell(nullptr, selfSpellId, true, nullptr, aurEff);
+ caster->CastSpell(nullptr, petSpellId, true, nullptr, aurEff);
if (roll_chance_i(impSoulLeech->GetAmount()))
- caster->CastSpell((Unit*)nullptr, SPELL_REPLENISHMENT, true, nullptr, aurEff);
+ caster->CastSpell(nullptr, SPELL_REPLENISHMENT, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp
index 4c859f5c8bc..3d6791a0391 100644
--- a/src/server/scripts/Spells/spell_warrior.cpp
+++ b/src/server/scripts/Spells/spell_warrior.cpp
@@ -444,13 +444,13 @@ class spell_warr_extra_proc : public SpellScriptLoader
if (!roll_chance_i(bonusAurEff->GetAmount()))
return;
- target->CastSpell((Unit*)nullptr, SPELL_WARRIOR_EXTRA_CHARGE, true, nullptr, aurEff);
+ target->CastSpell(nullptr, SPELL_WARRIOR_EXTRA_CHARGE, true, nullptr, aurEff);
SpellInfo const* auraInfo = aurEff->GetSpellInfo();
if (auraInfo->IsRankOf(sSpellMgr->AssertSpellInfo(SPELL_WARRIOR_BLOODSURGE_R1)))
- target->CastSpell((Unit*)nullptr, SPELL_WARRIOR_SLAM_GCD_REDUCED, true, nullptr, aurEff);
+ target->CastSpell(nullptr, SPELL_WARRIOR_SLAM_GCD_REDUCED, true, nullptr, aurEff);
else if (auraInfo->IsRankOf(sSpellMgr->AssertSpellInfo(SPELL_WARRIOR_SUDDEN_DEATH_R1)))
- target->CastSpell((Unit*)nullptr, SPELL_WARRIOR_EXECUTE_GCD_REDUCED, true, nullptr, aurEff);
+ target->CastSpell(nullptr, SPELL_WARRIOR_EXECUTE_GCD_REDUCED, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/World/action_ip_logger.cpp b/src/server/scripts/World/action_ip_logger.cpp
index 9dc3fba9896..9e894a52104 100644
--- a/src/server/scripts/World/action_ip_logger.cpp
+++ b/src/server/scripts/World/action_ip_logger.cpp
@@ -144,7 +144,7 @@ class AccountActionIpLogger : public AccountScript
stmt->setUInt32(1, characterGuid);
stmt->setUInt8(2, aType);
stmt->setUInt32(3, playerGuid);
- stmt->setString(4, systemNote.c_str());
+ stmt->setString(4, systemNote);
LoginDatabase.Execute(stmt);
}
else // ... but for failed login, we query last_attempt_ip from account table. Which we do with an unique query
@@ -155,7 +155,7 @@ class AccountActionIpLogger : public AccountScript
stmt->setUInt32(1, characterGuid);
stmt->setUInt8(2, aType);
stmt->setUInt32(3, playerGuid);
- stmt->setString(4, systemNote.c_str());
+ stmt->setString(4, systemNote);
LoginDatabase.Execute(stmt);
}
return;
@@ -236,8 +236,8 @@ class CharacterActionIpLogger : public PlayerScript
stmt->setUInt32(0, playerGuid);
stmt->setUInt32(1, characterGuid);
stmt->setUInt8(2, aType);
- stmt->setString(3, currentIp.c_str()); // We query the ip here.
- stmt->setString(4, systemNote.c_str());
+ stmt->setString(3, currentIp); // We query the ip here.
+ stmt->setString(4, systemNote);
// Seeing as the time differences should be minimal, we do not get unixtime and the timestamp right now;
// Rather, we let it be added with the SQL query.
@@ -297,7 +297,7 @@ public:
stmt2->setUInt32(1, characterGuid);
stmt2->setUInt8(2, aType);
stmt2->setUInt32(3, playerGuid);
- stmt2->setString(4, systemNote.c_str());
+ stmt2->setString(4, systemNote);
// Seeing as the time differences should be minimal, we do not get unixtime and the timestamp right now;
// Rather, we let it be added with the SQL query.
diff --git a/src/server/scripts/World/areatrigger_scripts.cpp b/src/server/scripts/World/areatrigger_scripts.cpp
index a7d730f185a..0e603e515e1 100644
--- a/src/server/scripts/World/areatrigger_scripts.cpp
+++ b/src/server/scripts/World/areatrigger_scripts.cpp
@@ -291,6 +291,38 @@ class AreaTrigger_at_nats_landing : public AreaTriggerScript
};
/*######
+## at_sentry_point
+######*/
+
+enum SentryPoint
+{
+ SPELL_TELEPORT_VISUAL = 799, // TODO Find the correct spell
+ QUEST_MISSING_DIPLO_PT14 = 1265,
+ NPC_TERVOSH = 4967
+};
+
+class AreaTrigger_at_sentry_point : public AreaTriggerScript
+{
+public:
+ AreaTrigger_at_sentry_point() : AreaTriggerScript("at_sentry_point") { }
+
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/)
+ {
+ QuestStatus quest_status = player->GetQuestStatus(QUEST_MISSING_DIPLO_PT14);
+ if (!player->IsAlive() || quest_status == QUEST_STATUS_NONE || quest_status == QUEST_STATUS_REWARDED)
+ return false;
+
+ if (!player->FindNearestCreature(NPC_TERVOSH, 100.0f))
+ {
+ if (Creature* tervosh = player->SummonCreature(NPC_TERVOSH, -3476.51f, -4105.94f, 17.1f, 5.3816f, TEMPSUMMON_TIMED_DESPAWN, 60000))
+ tervosh->CastSpell(tervosh, SPELL_TELEPORT_VISUAL, true);
+ }
+
+ return true;
+ }
+};
+
+/*######
## at_brewfest
######*/
@@ -488,6 +520,7 @@ void AddSC_areatrigger_scripts()
new AreaTrigger_at_last_rites();
new AreaTrigger_at_sholazar_waygate();
new AreaTrigger_at_nats_landing();
+ new AreaTrigger_at_sentry_point();
new AreaTrigger_at_brewfest();
new AreaTrigger_at_area_52_entrance();
new AreaTrigger_at_frostgrips_hollow();
diff --git a/src/server/scripts/World/boss_emerald_dragons.cpp b/src/server/scripts/World/boss_emerald_dragons.cpp
index f510b5c6839..96daefc124c 100644
--- a/src/server/scripts/World/boss_emerald_dragons.cpp
+++ b/src/server/scripts/World/boss_emerald_dragons.cpp
@@ -398,7 +398,7 @@ class boss_lethon : public CreatureScript
switch (eventId)
{
case EVENT_SHADOW_BOLT_WHIRL:
- me->CastSpell((Unit*)nullptr, SPELL_SHADOW_BOLT_WHIRL, false);
+ me->CastSpell(nullptr, SPELL_SHADOW_BOLT_WHIRL, false);
events.ScheduleEvent(EVENT_SHADOW_BOLT_WHIRL, urand(15000, 30000));
break;
default:
@@ -438,7 +438,7 @@ class npc_spirit_shade : public CreatureScript
{
if (moveType == FOLLOW_MOTION_TYPE && data == _summonerGuid.GetCounter())
{
- me->CastSpell((Unit*)nullptr, SPELL_DARK_OFFERING, false);
+ me->CastSpell(nullptr, SPELL_DARK_OFFERING, false);
me->DespawnOrUnsummon(1000);
}
}
diff --git a/src/server/scripts/World/go_scripts.cpp b/src/server/scripts/World/go_scripts.cpp
index d9aa9358ee7..91b7bf30ad7 100644
--- a/src/server/scripts/World/go_scripts.cpp
+++ b/src/server/scripts/World/go_scripts.cpp
@@ -37,7 +37,6 @@ go_soulwell
go_bashir_crystalforge
go_soulwell
go_dragonflayer_cage
-go_tadpole_cage
go_amberpine_outhouse
go_hive_pod
go_veil_skith_cage
@@ -1232,49 +1231,6 @@ public:
};
/*######
-## Quest 11560: Oh Noes, the Tadpoles!
-## go_tadpole_cage
-######*/
-
-enum Tadpoles
-{
- QUEST_OH_NOES_THE_TADPOLES = 11560,
- NPC_WINTERFIN_TADPOLE = 25201
-};
-
-class go_tadpole_cage : public GameObjectScript
-{
-public:
- go_tadpole_cage() : GameObjectScript("go_tadpole_cage") { }
-
- struct go_tadpole_cageAI : public GameObjectAI
- {
- go_tadpole_cageAI(GameObject* go) : GameObjectAI(go) { }
-
- bool GossipHello(Player* player) override
- {
- me->UseDoorOrButton();
- if (player->GetQuestStatus(QUEST_OH_NOES_THE_TADPOLES) == QUEST_STATUS_INCOMPLETE)
- {
- Creature* pTadpole = me->FindNearestCreature(NPC_WINTERFIN_TADPOLE, 1.0f);
- if (pTadpole)
- {
- pTadpole->DisappearAndDie();
- player->KilledMonsterCredit(NPC_WINTERFIN_TADPOLE);
- //FIX: Summon minion tadpole
- }
- }
- return true;
- }
- };
-
- GameObjectAI* GetAI(GameObject* go) const override
- {
- return new go_tadpole_cageAI(go);
- }
-};
-
-/*######
## go_amberpine_outhouse
######*/
@@ -1528,10 +1484,18 @@ public:
enum MidsummerPoleRibbon
{
- SPELL_POLE_DANCE = 29726,
- SPELL_BLUE_FIRE_RING = 46842,
- NPC_POLE_RIBBON_BUNNY = 17066,
- ACTION_COSMETIC_FIRES = 0
+ SPELL_TEST_RIBBON_POLE_1 = 29705,
+ SPELL_TEST_RIBBON_POLE_2 = 29726,
+ SPELL_TEST_RIBBON_POLE_3 = 29727,
+ NPC_POLE_RIBBON_BUNNY = 17066,
+ ACTION_COSMETIC_FIRES = 0
+};
+
+uint32 const RibbonPoleSpells[3] =
+{
+ SPELL_TEST_RIBBON_POLE_1,
+ SPELL_TEST_RIBBON_POLE_2,
+ SPELL_TEST_RIBBON_POLE_3
};
class go_midsummer_ribbon_pole : public GameObjectScript
@@ -1548,7 +1512,7 @@ public:
if (Creature* creature = me->FindNearestCreature(NPC_POLE_RIBBON_BUNNY, 10.0f))
{
creature->GetAI()->DoAction(ACTION_COSMETIC_FIRES);
- player->CastSpell(creature, SPELL_POLE_DANCE, true);
+ player->CastSpell(player, RibbonPoleSpells[urand(0, 2)], true);
}
return true;
}
@@ -1679,43 +1643,99 @@ public:
case EVENT_BM_START_MUSIC:
if (!IsHolidayActive(HOLIDAY_BREWFEST)) // Check if Brewfest is active
break;
- // Check if gob is correct area, play music, set time of music
- if (me->GetAreaId() == SILVERMOON || me->GetAreaId() == UNDERCITY || me->GetAreaId() == ORGRIMMAR_1 || me->GetAreaId() == ORGRIMMAR_2 || me->GetAreaId() == THUNDERBLUFF || me->GetAreaId() == SHATTRATH)
- {
- if (rnd == 0)
- {
- me->PlayDirectMusic(EVENT_BREWFESTGOBLIN01);
- musicTime = EVENT_BREWFESTGOBLIN01_TIME;
- }
- else if (rnd == 1)
- {
- me->PlayDirectMusic(EVENT_BREWFESTGOBLIN02);
- musicTime = EVENT_BREWFESTGOBLIN02_TIME;
- }
- else
- {
- me->PlayDirectMusic(EVENT_BREWFESTGOBLIN03);
- musicTime = EVENT_BREWFESTGOBLIN03_TIME;
- }
- }
- if (me->GetAreaId() == IRONFORGE_1 || me->GetAreaId() == IRONFORGE_2 || me->GetAreaId() == STORMWIND || me->GetAreaId() == EXODAR || me->GetAreaId() == DARNASSUS || me->GetAreaId() == SHATTRATH)
+
+ switch (me->GetAreaId())
{
- if (rnd == 0)
- {
- me->PlayDirectMusic(EVENT_BREWFESTDWARF01);
- musicTime = EVENT_BREWFESTDWARF01_TIME;
- }
- else if (rnd == 1)
- {
- me->PlayDirectMusic(EVENT_BREWFESTDWARF02);
- musicTime = EVENT_BREWFESTDWARF02_TIME;
- }
- else
- {
- me->PlayDirectMusic(EVENT_BREWFESTDWARF03);
- musicTime = EVENT_BREWFESTDWARF03_TIME;
- }
+ // Horde
+ case SILVERMOON:
+ case UNDERCITY:
+ case ORGRIMMAR_1:
+ case ORGRIMMAR_2:
+ case THUNDERBLUFF:
+ if (rnd == 0)
+ {
+ me->PlayDirectMusic(EVENT_BREWFESTGOBLIN01);
+ musicTime = EVENT_BREWFESTGOBLIN01_TIME;
+ }
+ else if (rnd == 1)
+ {
+ me->PlayDirectMusic(EVENT_BREWFESTGOBLIN02);
+ musicTime = EVENT_BREWFESTGOBLIN02_TIME;
+ }
+ else
+ {
+ me->PlayDirectMusic(EVENT_BREWFESTGOBLIN03);
+ musicTime = EVENT_BREWFESTGOBLIN03_TIME;
+ }
+ break;
+ // Alliance
+ case IRONFORGE_1:
+ case IRONFORGE_2:
+ case STORMWIND:
+ case EXODAR:
+ case DARNASSUS:
+ if (rnd == 0)
+ {
+ me->PlayDirectMusic(EVENT_BREWFESTDWARF01);
+ musicTime = EVENT_BREWFESTDWARF01_TIME;
+ }
+ else if (rnd == 1)
+ {
+ me->PlayDirectMusic(EVENT_BREWFESTDWARF02);
+ musicTime = EVENT_BREWFESTDWARF02_TIME;
+ }
+ else
+ {
+ me->PlayDirectMusic(EVENT_BREWFESTDWARF03);
+ musicTime = EVENT_BREWFESTDWARF03_TIME;
+ }
+ break;
+ // Neurtal
+ case SHATTRATH:
+ std::vector<Player*> playersNearby;
+ me->GetPlayerListInGrid(playersNearby, me->GetVisibilityRange());
+ for (Player* player : playersNearby)
+ {
+ if (player->GetTeamId() == TEAM_HORDE)
+ {
+ if (rnd == 0)
+ {
+ me->PlayDirectMusic(EVENT_BREWFESTGOBLIN01);
+ musicTime = EVENT_BREWFESTGOBLIN01_TIME;
+ }
+ else if (rnd == 1)
+ {
+ me->PlayDirectMusic(EVENT_BREWFESTGOBLIN02);
+ musicTime = EVENT_BREWFESTGOBLIN02_TIME;
+ }
+ else
+ {
+ me->PlayDirectMusic(EVENT_BREWFESTGOBLIN03);
+ musicTime = EVENT_BREWFESTGOBLIN03_TIME;
+ }
+ }
+ else
+ {
+ if (rnd == 0)
+ {
+ me->PlayDirectMusic(EVENT_BREWFESTDWARF01);
+ musicTime = EVENT_BREWFESTDWARF01_TIME;
+ }
+ else if (rnd == 1)
+ {
+ me->PlayDirectMusic(EVENT_BREWFESTDWARF02);
+ musicTime = EVENT_BREWFESTDWARF02_TIME;
+ }
+ else
+ {
+ me->PlayDirectMusic(EVENT_BREWFESTDWARF03);
+ musicTime = EVENT_BREWFESTDWARF03_TIME;
+ }
+ }
+ }
+ break;
}
+
_events.ScheduleEvent(EVENT_BM_START_MUSIC, 5000); // Every 5 second's SMSG_PLAY_MUSIC packet (PlayDirectMusic) is pushed to the client
break;
default:
@@ -2045,7 +2065,6 @@ void AddSC_go_scripts()
new go_table_theka();
new go_inconspicuous_landmark();
new go_soulwell();
- new go_tadpole_cage();
new go_dragonflayer_cage();
new go_amberpine_outhouse();
new go_hive_pod();
diff --git a/src/server/scripts/World/item_scripts.cpp b/src/server/scripts/World/item_scripts.cpp
index e5b3735a22e..ac231434c83 100644
--- a/src/server/scripts/World/item_scripts.cpp
+++ b/src/server/scripts/World/item_scripts.cpp
@@ -363,33 +363,6 @@ public:
}
};
-enum TheEmissary
-{
- QUEST_THE_EMISSARY = 11626,
- NPC_LEVIROTH = 26452
-};
-
-class item_trident_of_nazjan : public ItemScript
-{
-public:
- item_trident_of_nazjan() : ItemScript("item_Trident_of_Nazjan") { }
-
- bool OnUse(Player* player, Item* item, SpellCastTargets const& /*targets*/) override
- {
- if (player->GetQuestStatus(QUEST_THE_EMISSARY) == QUEST_STATUS_INCOMPLETE)
- {
- if (Creature* pLeviroth = player->FindNearestCreature(NPC_LEVIROTH, 10.0f)) // spell range
- {
- pLeviroth->AI()->AttackStart(player);
- return false;
- } else
- player->SendEquipError(EQUIP_ERR_OUT_OF_RANGE, item, nullptr);
- } else
- player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, item, nullptr);
- return true;
- }
-};
-
enum CapturedFrog
{
QUEST_THE_PERFECT_SPIES = 25444,
@@ -451,7 +424,6 @@ void AddSC_item_scripts()
new item_pile_fake_furs();
new item_petrov_cluster_bombs();
new item_dehta_trap_smasher();
- new item_trident_of_nazjan();
new item_captured_frog();
new item_generic_limit_chance_above_60();
}
diff --git a/src/server/scripts/World/npc_innkeeper.cpp b/src/server/scripts/World/npc_innkeeper.cpp
index 7db733c7f78..dd59d2c0aa8 100644
--- a/src/server/scripts/World/npc_innkeeper.cpp
+++ b/src/server/scripts/World/npc_innkeeper.cpp
@@ -42,7 +42,14 @@ enum Spells
#define LOCALE_TRICK_OR_TREAT_6 "¡Truco o trato!"
#define LOCALE_INNKEEPER_0 "Make this inn my home."
+#define LOCALE_INNKEEPER_2 "Faites de cette auberge votre foyer."
#define LOCALE_INNKEEPER_3 "Ich möchte dieses Gasthaus zu meinem Heimatort machen."
+#define LOCALE_INNKEEPER_6 "Fija tu hogar en esta taberna."
+
+#define LOCALE_VENDOR_0 "I want to browse your goods."
+#define LOCALE_VENDOR_2 "Je voudrais regarder vos articles."
+#define LOCALE_VENDOR_3 "Ich sehe mich nur mal um."
+#define LOCALE_VENDOR_6 "Quiero ver tus mercancías."
class npc_innkeeper : public CreatureScript
{
@@ -72,14 +79,26 @@ public:
player->PrepareQuestMenu(me->GetGUID());
if (me->IsVendor())
- AddGossipItemFor(player, GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
+ {
+ char const* localizedEntry;
+ switch (player->GetSession()->GetSessionDbcLocale())
+ {
+ case LOCALE_frFR: localizedEntry = LOCALE_VENDOR_2; break;
+ case LOCALE_deDE: localizedEntry = LOCALE_VENDOR_3; break;
+ case LOCALE_esES: localizedEntry = LOCALE_VENDOR_6; break;
+ case LOCALE_enUS: default: localizedEntry = LOCALE_VENDOR_0;
+ }
+ AddGossipItemFor(player, GOSSIP_ICON_VENDOR, localizedEntry, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
+ }
if (me->IsInnkeeper())
{
char const* localizedEntry;
switch (player->GetSession()->GetSessionDbcLocale())
{
+ case LOCALE_frFR: localizedEntry = LOCALE_INNKEEPER_2; break;
case LOCALE_deDE: localizedEntry = LOCALE_INNKEEPER_3; break;
+ case LOCALE_esES: localizedEntry = LOCALE_INNKEEPER_6; break;
case LOCALE_enUS: default: localizedEntry = LOCALE_INNKEEPER_0;
}
AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, localizedEntry, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INN);
diff --git a/src/server/scripts/World/npc_professions.cpp b/src/server/scripts/World/npc_professions.cpp
index 9f1df957784..b68722b7ff8 100644
--- a/src/server/scripts/World/npc_professions.cpp
+++ b/src/server/scripts/World/npc_professions.cpp
@@ -64,15 +64,6 @@ A few notes for future developement:
# 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"
@@ -168,19 +159,7 @@ enum ProfessionSpells
S_UNLEARN_SPELLFIRE = 41299,
S_UNLEARN_MOONCLOTH = 41558,
- S_UNLEARN_SHADOWEAVE = 41559,
-
- S_TRANSMUTE = 28672,
- S_ELIXIR = 28677,
- S_POTION = 28675,
-
- S_LEARN_TRANSMUTE = 28674,
- S_LEARN_ELIXIR = 28678,
- S_LEARN_POTION = 28676,
-
- S_UNLEARN_TRANSMUTE = 41565,
- S_UNLEARN_ELIXIR = 41564,
- S_UNLEARN_POTION = 41563,
+ S_UNLEARN_SHADOWEAVE = 41559
};
/*###
@@ -188,11 +167,6 @@ enum ProfessionSpells
###*/
enum SpecializationTrainers
{
- /* Alchemy */
- N_TRAINER_TRANSMUTE = 22427, // Zarevhi
- N_TRAINER_ELIXIR = 19052, // Lorokeem
- N_TRAINER_POTION = 17909, // Lauranna Thar'well
-
/* Blacksmithing */
N_TRAINER_SMITHOMNI1 = 11145, // Myolor Sunderfury
N_TRAINER_SMITHOMNI2 = 11176, // Krathok Moltenfist
@@ -219,26 +193,15 @@ enum SpecializationTrainers
};
/*###
-# specialization quests
-###*/
-enum SpecializationQuests
-{
- /* Alchemy */
- Q_MASTER_TRANSMUTE = 10899,
- Q_MASTER_ELIXIR = 10902,
- Q_MASTER_POTION = 10897,
-};
-
-/*###
# formulas to calculate unlearning cost
###*/
-int32 DoLearnCost(Player* /*player*/) //tailor, alchemy
+int32 DoLearnCost(Player* /*player*/) //tailor
{
return 200000;
}
-int32 DoHighUnlearnCost(Player* /*player*/) //tailor, alchemy
+int32 DoHighUnlearnCost(Player* /*player*/) //tailor
{
return 1500000;
}
@@ -441,183 +404,6 @@ void ProcessUnlearnAction(Player* player, Creature* creature, uint32 spellId, ui
}
/*###
-# start menues alchemy
-###*/
-
-class npc_prof_alchemy : public CreatureScript
-{
-public:
- npc_prof_alchemy() : CreatureScript("npc_prof_alchemy") { }
-
- struct npc_prof_alchemyAI : public ScriptedAI
- {
- npc_prof_alchemyAI(Creature* creature) : ScriptedAI(creature) { }
-
- inline bool HasAlchemySpell(Player* player)
- {
- return (player->HasSpell(S_TRANSMUTE) || player->HasSpell(S_ELIXIR) || player->HasSpell(S_POTION));
- }
-
- bool GossipHello(Player* player) override
- {
- if (me->IsQuestGiver())
- player->PrepareQuestMenu(me->GetGUID());
-
- if (me->IsVendor())
- AddGossipItemFor(player, GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
-
- if (me->IsTrainer())
- AddGossipItemFor(player, GOSSIP_ICON_TRAINER, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN);
-
- if (player->HasSkill(SKILL_ALCHEMY) && player->GetBaseSkillValue(SKILL_ALCHEMY) >= 350 && player->getLevel() > 67)
- {
- if (player->GetQuestRewardStatus(Q_MASTER_TRANSMUTE) || player->GetQuestRewardStatus(Q_MASTER_ELIXIR) || player->GetQuestRewardStatus(Q_MASTER_POTION))
- {
- switch (me->GetEntry())
- {
- case N_TRAINER_TRANSMUTE: //Zarevhi
- if (!HasAlchemySpell(player))
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_LEARN_TRANSMUTE, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 1);
- if (player->HasSpell(S_TRANSMUTE))
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_TRANSMUTE, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 4);
- break;
- case N_TRAINER_ELIXIR: //Lorokeem
- if (!HasAlchemySpell(player))
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_LEARN_ELIXIR, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 2);
- if (player->HasSpell(S_ELIXIR))
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_ELIXIR, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 5);
- break;
- case N_TRAINER_POTION: //Lauranna Thar'well
- if (!HasAlchemySpell(player))
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_LEARN_POTION, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 3);
- if (player->HasSpell(S_POTION))
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_POTION, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 6);
- break;
- }
- }
- }
-
- SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
- return true;
- }
-
- void SendActionMenu(Player* player, uint32 action)
- {
- switch (action)
- {
- case GOSSIP_ACTION_TRADE:
- player->GetSession()->SendListInventory(me->GetGUID());
- break;
- case GOSSIP_ACTION_TRAIN:
- player->GetSession()->SendTrainerList(me->GetGUID());
- break;
- //Learn Alchemy
- case GOSSIP_ACTION_INFO_DEF + 1:
- ProcessCastaction(player, me, S_TRANSMUTE, S_LEARN_TRANSMUTE, DoLearnCost(player));
- break;
- case GOSSIP_ACTION_INFO_DEF + 2:
- ProcessCastaction(player, me, S_ELIXIR, S_LEARN_ELIXIR, DoLearnCost(player));
- break;
- case GOSSIP_ACTION_INFO_DEF + 3:
- ProcessCastaction(player, me, S_POTION, S_LEARN_POTION, DoLearnCost(player));
- break;
- //Unlearn Alchemy
- case GOSSIP_ACTION_INFO_DEF + 4:
- ProcessCastaction(player, me, 0, S_UNLEARN_TRANSMUTE, DoHighUnlearnCost(player));
- break;
- case GOSSIP_ACTION_INFO_DEF + 5:
- ProcessCastaction(player, me, 0, S_UNLEARN_ELIXIR, DoHighUnlearnCost(player));
- break;
- case GOSSIP_ACTION_INFO_DEF + 6:
- ProcessCastaction(player, me, 0, S_UNLEARN_POTION, DoHighUnlearnCost(player));
- break;
- }
- }
-
- void SendConfirmLearn(Player* player, uint32 action)
- {
- if (action)
- {
- switch (me->GetEntry())
- {
- case N_TRAINER_TRANSMUTE:
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_LEARN_TRANSMUTE, GOSSIP_SENDER_CHECK, action);
- //unknown textID ()
- SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
- break;
- case N_TRAINER_ELIXIR:
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_LEARN_ELIXIR, GOSSIP_SENDER_CHECK, action);
- //unknown textID ()
- SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
- break;
- case N_TRAINER_POTION:
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_LEARN_POTION, GOSSIP_SENDER_CHECK, action);
- //unknown textID ()
- SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
- break;
- }
- }
- }
-
- void SendConfirmUnlearn(Player* player, uint32 action)
- {
- if (action)
- {
- switch (me->GetEntry())
- {
- case N_TRAINER_TRANSMUTE:
- AddGossipItemFor(player, 0, GOSSIP_UNLEARN_TRANSMUTE, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_ALCHEMY_SPEC, DoHighUnlearnCost(player), false);
- //unknown textID ()
- SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
- break;
- case N_TRAINER_ELIXIR:
- AddGossipItemFor(player, 0, GOSSIP_UNLEARN_ELIXIR, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_ALCHEMY_SPEC, DoHighUnlearnCost(player), false);
- //unknown textID ()
- SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
- break;
- case N_TRAINER_POTION:
- AddGossipItemFor(player, 0, GOSSIP_UNLEARN_POTION, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_ALCHEMY_SPEC, DoHighUnlearnCost(player), false);
- //unknown textID ()
- SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
- break;
- }
- }
- }
-
- bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
- {
- uint32 const sender = player->PlayerTalkClass->GetGossipOptionSender(gossipListId);
- uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
- ClearGossipMenuFor(player);
- switch (sender)
- {
- case GOSSIP_SENDER_MAIN:
- SendActionMenu(player, action);
- break;
-
- case GOSSIP_SENDER_LEARN:
- SendConfirmLearn(player, action);
- break;
-
- case GOSSIP_SENDER_UNLEARN:
- SendConfirmUnlearn(player, action);
- break;
-
- case GOSSIP_SENDER_CHECK:
- SendActionMenu(player, action);
- break;
- }
- return true;
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_prof_alchemyAI(creature);
- }
-};
-
-/*###
# start menues blacksmith
###*/
@@ -1365,7 +1151,6 @@ public:
void AddSC_npc_professions()
{
- new npc_prof_alchemy();
new npc_prof_blacksmith();
new npc_engineering_tele_trinket();
new go_soothsaying_for_dummies();
diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp
index 03631c5b808..0e19b5f7bb4 100644
--- a/src/server/scripts/World/npcs_special.cpp
+++ b/src/server/scripts/World/npcs_special.cpp
@@ -457,8 +457,7 @@ public:
enum TorchTossingTarget
{
- NPC_TORCH_TOSSING_TARGET_BUNNY = 25535,
- SPELL_TARGET_INDICATOR = 45723
+ SPELL_TORCH_TARGET_PICKER = 45907
};
class npc_torch_tossing_target_bunny_controller : public CreatureScript
@@ -468,42 +467,28 @@ public:
struct npc_torch_tossing_target_bunny_controllerAI : public ScriptedAI
{
- npc_torch_tossing_target_bunny_controllerAI(Creature* creature) : ScriptedAI(creature)
- {
- _targetTimer = 3000;
- }
+ npc_torch_tossing_target_bunny_controllerAI(Creature* creature) : ScriptedAI(creature) { }
- ObjectGuid DoSearchForTargets(ObjectGuid lastTargetGUID)
+ void Reset() override
{
- std::list<Creature*> targets;
- me->GetCreatureListWithEntryInGrid(targets, NPC_TORCH_TOSSING_TARGET_BUNNY, 60.0f);
- targets.remove_if([lastTargetGUID](Creature* creature) { return creature->GetGUID() == lastTargetGUID; });
-
- if (!targets.empty())
+ _scheduler.Schedule(Seconds(2), [this](TaskContext context)
{
- _lastTargetGUID = Trinity::Containers::SelectRandomContainerElement(targets)->GetGUID();
-
- return _lastTargetGUID;
- }
- return ObjectGuid::Empty;
+ me->CastCustomSpell(SPELL_TORCH_TARGET_PICKER, SPELLVALUE_MAX_TARGETS, 1);
+ _scheduler.Schedule(Seconds(3), [this](TaskContext /*context*/)
+ {
+ me->CastCustomSpell(SPELL_TORCH_TARGET_PICKER, SPELLVALUE_MAX_TARGETS, 1);
+ });
+ context.Repeat(Seconds(5));
+ });
}
void UpdateAI(uint32 diff) override
{
- if (_targetTimer < diff)
- {
- if (Unit* target = ObjectAccessor::GetUnit(*me, DoSearchForTargets(_lastTargetGUID)))
- target->CastSpell(target, SPELL_TARGET_INDICATOR, true);
-
- _targetTimer = 3000;
- }
- else
- _targetTimer -= diff;
+ _scheduler.Update(diff);
}
private:
- uint32 _targetTimer;
- ObjectGuid _lastTargetGUID;
+ TaskScheduler _scheduler;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -1040,9 +1025,9 @@ class npc_garments_of_quests : public CreatureScript
public:
npc_garments_of_quests() : CreatureScript("npc_garments_of_quests") { }
- struct npc_garments_of_questsAI : public npc_escortAI
+ struct npc_garments_of_questsAI : public EscortAI
{
- npc_garments_of_questsAI(Creature* creature) : npc_escortAI(creature)
+ npc_garments_of_questsAI(Creature* creature) : EscortAI(creature)
{
switch (me->GetEntry())
{
@@ -1130,11 +1115,6 @@ public:
}
}
- void WaypointReached(uint32 /*waypointId*/) override
- {
-
- }
-
void UpdateAI(uint32 diff) override
{
if (CanRun && !me->IsInCombat())
@@ -1165,7 +1145,7 @@ public:
RunAwayTimer -= diff;
}
- npc_escortAI::UpdateAI(diff);
+ EscortAI::UpdateAI(diff);
}
};
@@ -1603,7 +1583,7 @@ class npc_tournament_mount : public CreatureScript
if (apply)
{
_pennantSpellId = GetPennantSpellId(player);
- player->CastSpell((Unit*)nullptr, _pennantSpellId, true);
+ player->CastSpell(nullptr, _pennantSpellId, true);
}
else
player->RemoveAurasDueToSpell(_pennantSpellId);
diff --git a/src/server/shared/DataStores/DBCStore.cpp b/src/server/shared/DataStores/DBCStore.cpp
index 30cae057f90..b81b82e87b9 100644
--- a/src/server/shared/DataStores/DBCStore.cpp
+++ b/src/server/shared/DataStores/DBCStore.cpp
@@ -18,7 +18,7 @@
#include "DBCStore.h"
#include "DBCDatabaseLoader.h"
-DBCStorageBase::DBCStorageBase(char const* fmt) : _fieldCount(0), _fileFormat(fmt), _dataTable(nullptr), _indexTableSize(0)
+DBCStorageBase::DBCStorageBase(char const* fmt) : _fieldCount(0), _fileFormat(fmt), _dataTable(nullptr), _dataTableEx(nullptr), _indexTableSize(0)
{
}
diff --git a/src/server/shared/Packets/ByteBuffer.cpp b/src/server/shared/Packets/ByteBuffer.cpp
index a4ab6e1daf7..aeab874f635 100644
--- a/src/server/shared/Packets/ByteBuffer.cpp
+++ b/src/server/shared/Packets/ByteBuffer.cpp
@@ -169,7 +169,7 @@ void ByteBuffer::hexlike() const
for (uint32 i = 0; i < size(); ++i)
{
char buf[3];
- snprintf(buf, 3, "%2X ", read<uint8>(i));
+ snprintf(buf, 3, "%2X", read<uint8>(i));
if ((i == (j * 8)) && ((i != (k * 16))))
{
o << "| ";
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index ba8a10c759d..78d18651724 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -16,6 +16,7 @@
# WARDEN SETTINGS
# PLAYER INTERACTION
# CREATURE SETTINGS
+# SPAWN/RESPAWN SETTINGS
# CHAT SETTINGS
# GAME MASTER SETTINGS
# VISIBILITY AND DISTANCES
@@ -1104,6 +1105,34 @@ MaxGroupXPDistance = 74
MaxRecruitAFriendBonusDistance = 100
#
+# MinQuestScaledXPRatio
+# Description: Min ratio of experience that a quest can grant when player level scaling is factored.
+# Example: 50 (No less than 50% experience granted from a lower leveled quests completion)
+# 100 (Quests always grant full experience upon completion)
+# Default: 0 - (Quests too low may grant no experience)
+
+MinQuestScaledXPRatio = 0
+
+#
+# MinCreatureScaledXPRatio
+# Description: Min ratio of experience that a creature kill can grant when player level scaling is factored. This
+# will also allow spell procs to trigger, such as Drain Soul, if > 0 and exp is grantable.
+# Example: 50 (No less than 50% experience granted from a lower leveled creature kill)
+# 100 (Creature kills always grant full experience upon kill)
+# Default: 0 - (Creatures too low may grant no experience)
+
+MinCreatureScaledXPRatio = 0
+
+#
+# MinDiscoveredScaledXPRatio
+# Description: Min ratio of experience that an area discovery event will grant when player level scaling is factored.
+# Example: 50 (No less than 50% experience granted from discovering a new section of map)
+# 100 (Map exploration always grant full experience upon discovery)
+# Default: 0 - (No experience granted when discovered area is too low level)
+
+MinDiscoveredScaledXPRatio = 0
+
+#
# MailDeliveryDelay
# Description: Time (in seconds) mail delivery is delayed when sending items.
# Default: 3600 - (1 hour)
@@ -1111,6 +1140,14 @@ MaxRecruitAFriendBonusDistance = 100
MailDeliveryDelay = 3600
#
+# CleanOldMailTime
+# Description: The hour at which old mails will be returned or deleted by the server.
+# This can be any integer number from 0 to 23. 20 will be 8pm server time.
+# Default: 4 - 4am
+
+CleanOldMailTime = 4
+
+#
# SkillChance.Prospecting
# Description: Allow skill increase from prospecting.
# Default: 0 - (Disabled)
@@ -1710,6 +1747,130 @@ ListenRange.Yell = 300
Creature.MovingStopTimeForPlayer = 180000
+# MonsterSight
+# Description: The maximum distance in yards that a "monster" creature can see
+# regardless of level difference (through CreatureAI::IsVisible).
+# Increases CONFIG_SIGHT_MONSTER to 50 yards. Used to be 20 yards.
+# Default: 50.000000
+
+MonsterSight = 50.000000
+
+#
+###################################################################################################
+
+###################################################################################################
+# SPAWN/RESPAWN SETTINGS
+#
+# Respawn.MinCheckIntervalMS
+# Description: Minimum time that needs to pass between respawn checks for any given map.
+# Default: 5000 - 5 seconds
+
+Respawn.MinCheckIntervalMS = 5000
+
+#
+# Respawn.GuidWarnLevel
+# Description: The point at which the highest guid for creatures or gameobjects in any map must reach
+# before the warning logic is enabled. A restart will then be queued at the next quiet time
+# The maximum guid per map is 16,777,216. So, it must be less than this value.
+# Default: 12000000 - 12 million
+
+Respawn.GuidWarnLevel = 12000000
+
+#
+# Respawn.WarningMessage
+# Description: This message will be periodically shown (Frequency specified by Respawn.WarningFrequency) to
+# all users of the server, once the Respawn.GuidWarnLevel has been passed, and a restart scheduled.
+# It's used to warn users that there will be an out of schedule server restart soon.
+# Default: "There will be an unscheduled server restart at 03:00 server time. The server will be available again shortly after."
+
+Respawn.WarningMessage = "There will be an unscheduled server restart at 03:00. The server will be available again shortly after."
+
+#
+# Respawn.WarningFrequency
+# Description: The frequency (in seconds) that the warning message will be sent to users after a quiet time restart is triggered.
+# The message will repeat each time this many seconds passed until the server is restarted.
+# If set to 0, no warnings will be sent.
+# Default: 1800 - (30 minutes)
+
+Respawn.WarningFrequency = 1800
+
+#
+# Respawn.GuidAlertLevel
+# Description: The point at which the highest guid for creatures or gameobjects in any map must reach
+# before the alert logic is enabled. A restart will then be triggered for 30 mins from that
+# point. The maximum guid per map is 16,777,216. So, it must be less than this value.
+# Default: 16000000 - 16 million
+
+Respawn.GuidAlertLevel = 16000000
+
+#
+# Respawn.AlertRestartReason
+# Description: The shutdown reason given when the alert level is reached. The server will use a fixed time of
+# 5 minutes and the reason for shutdown will be this message
+# Default: "Urgent Maintenance"
+
+Respawn.AlertRestartReason = "Urgent Maintenance"
+
+#
+# Respawn.RestartQuietTime
+# Description: The hour at which the server will be restarted after the Respawn.GuidWarnLevel
+# threshold has been reached. This can be between 0 and 23. 20 will be 8pm server time
+# Default: 3 - 3am
+
+Respawn.RestartQuietTime = 3
+
+#
+# Respawn.DynamicMode
+# Description: Select which mode (if any) should be used to adjust respawn of creatures.
+# This will only affect creatures that have dynamic spawn rate scaling enabled in
+# the spawn group table (by default, gathering nodes and quest targets with respawn time <30min
+# 1 - Use number of players in zone
+# Default: 0 - No dynamic respawn function
+
+Respawn.DynamicMode = 0
+
+#
+# Respawn.DynamicEscortNPC
+# Description: This switch controls the dynamic respawn system for escort NPCs not in instancable maps (base maps only).
+# This will cause the respawn timer to begin when an escort event begins, and potentially
+# allow multiple instances of the NPC to be alive at the same time (when combined with Respawn.DynamicMode > 0)
+# 1 - Enabled
+# Default: 0 - Disabled
+
+Respawn.DynamicEscortNPC = 0
+
+#
+# Respawn.DynamicRateCreature
+# Description: The rate at which the respawn time is adjusted for high player counts in a zone (for creatures).
+# Up to this number of players, the respawn rate is unchanged.
+# At double this number in players, you get twice as many respawns, at three times this number, three times the respawns, and so forth.
+# Default: 10
+
+Respawn.DynamicRateCreature = 10
+
+#
+# Respawn.DynamicMinimumCreature
+# Description: The minimum respawn time for a creature under dynamic scaling.
+# Default: 10 - (10 seconds)
+
+Respawn.DynamicMinimumCreature = 10
+
+#
+# Respawn.DynamicRateGameObject
+# Description: The rate at which the respawn time is adjusted for high player counts in a zone (for gameobjects).
+# Up to this number of players, the respawn rate is unchanged.
+# At double this number in players, you get twice as many respawns, at three times this number, three times the respawns, and so forth.
+# Default: 10
+
+Respawn.DynamicRateGameObject = 10
+
+#
+# Respawn.DynamicMinimumGameObject
+# Description: The minimum respawn time for a gameobject under dynamic scaling.
+# Default: 10 - (10 seconds)
+
+Respawn.DynamicMinimumGameObject = 10
+
#
###################################################################################################