diff options
8 files changed, 780 insertions, 58 deletions
diff --git a/sql/updates/world/2013_01_04_00_world_halls_of_origination_434.sql b/sql/updates/world/2013_01_04_00_world_halls_of_origination_434.sql new file mode 100644 index 00000000000..36df0da72ca --- /dev/null +++ b/sql/updates/world/2013_01_04_00_world_halls_of_origination_434.sql @@ -0,0 +1,51 @@ +UPDATE `creature_template` SET `ScriptName`="npc_brann_bronzebeard_anraphet" WHERE `entry`=39908; +DELETE FROM `creature_text` WHERE `entry`=39908; +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES +(39908, 0, 0, 'Right, let''s go! Just need to input the final entry sequence into the door mechanism... and...', 12, 0, 100, 5, 0, 20897, 'Brann Bronzebeard'), +(39908, 1, 0, 'That did the trick! The control room should be right behind this... oh... wow...', 12, 0, 100, 5, 0, 20898, 'Brann Bronzebeard'), +(39908, 2, 0, 'What? This isn''t the control room! There''s another entire defense mechanism in place, and the blasted Rock Troggs broke into here somehow. Troggs. Why did it have to be Troggs!', 12, 0, 100, 5, 0, 20899, 'Brann Bronzebeard'), +(39908, 3, 0, 'Ok, let me think a moment.', 12, 0, 100, 1, 0, 20900, 'Brann Bronzebeard'), +(39908, 4, 0, 'Mirrors pointing all over the place.', 12, 0, 100, 25, 0, 20902, 'Brann Bronzebeard'), +(39908, 5, 0, 'Four platforms with huge elementals.', 12, 0, 100, 25, 0, 20901, 'Brann Bronzebeard'), +(39908, 6, 0, 'I got it! I saw a tablet that mentioned this chamber. This is the Vault of Lights! Ok, simple enough. I need you adventurers to take out each of the four elementals to trigger the opening sequence for the far door!', 12, 0, 100, 5, 0, 20903, 'Brann Bronzebeard'), +(39908, 7, 0, 'One down!', 14, 0, 100, 5, 0, 20904, 'Brann Bronzebeard'), +(39908, 8, 0, 'Another one down! Just look at those light beams! They seem to be connecting to the far door!', 14, 0, 100, 5, 0, 20905, 'Brann Bronzebeard'), +(39908, 9, 0, 'One more elemental to go! The door is almost open!', 14, 0, 100, 5, 0, 20906, 'Brann Bronzebeard'), +(39908, 10, 0, 'That''s it, you''ve done it! The vault door is opening! Now we can... oh, no!', 14, 0, 100, 5, 0, 20907, 'Brann Bronzebeard'), +(39908, 11, 0, 'We''ve done it! The control room is breached!', 14, 0, 100, 5, 0, 23709, 'Brann Bronzebeard'), +(39908, 12, 0, 'Here we go! Now this should only take a moment...', 14, 0, 100, 5, 0, 23710, 'Brann Bronzebeard'); + +UPDATE `creature_template` SET `ScriptName`="boss_anraphet" WHERE `entry`=39788; +DELETE FROM `creature_text` WHERE `entry`=39788; +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES +(39788, 0, 0, 'This unit has been activated outside normal operating protocols. Downloading new operational parameters. Download complete. Full unit self defense routines are now active. Destruction of foreign units in the system shall now commence.', 14, 0, 100, 0, 0, 20857, 'Anraphet - SAY_INTRO'), +(39788, 1, 0, 'Purge of unauthorized entities commencing.', 14, 0, 100, 0, 0, 20862, 'Anraphet - SAY_AGGRO'), +(39788, 2, 0, 'Omega Stance activated. Annihilation of foreign unit is now imminent.', 14, 0, 100, 0, 0, 20861, 'Anraphet - SAY_OMEGA_STANCE'), +(39788, 3, 0, 'Purge Complete.', 14, 0, 100, 0, 0, 20859, 'Anraphet - SAY_PLAYER_KILL'), +(39788, 3, 1, 'Target Annihilated.', 14, 0, 100, 0, 0, 20858, 'Anraphet - SAY_PLAYER_KILL'), +(39788, 4, 0, 'Anraphet unit shutting down...', 14, 0, 100, 0, 0, 20856, 'Anraphet - SAY_DEATH'); + +DELETE FROM `spell_script_names` WHERE `spell_id` IN (76904,77106,77127); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(76904,'spell_anraphet_alpha_beams'), +(77106,'spell_anraphet_omega_stance_summon'), +(77127,'spell_omega_stance_spider_effect'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup` IN (11339,11348,12512); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=11339; +INSERT INTO `conditions`(`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(14, 11339, 15794, 0, 0, 13, 1, 2, 3, 2, 1, 0, 0, '', 'Brann Bronzebeard gossip menu - Show only if DATA_VAULT_OF_LIGHTS is not done'), +(14, 11348, 15815, 0, 0, 13, 1, 18, 4, 0, 1, 0, 0, '', 'Brann Bronzebeard gossip menu - Show only if DATA_DEAD_ELEMENTALS is less than 4'), +(14, 12512, 17600, 0, 0, 13, 1, 18, 4, 0, 0, 0, 0, '', 'Brann Bronzebeard gossip menu - Show only if DATA_DEAD_ELEMENTALS is 4'), +(15, 11339, 0, 0, 0, 13, 1, 2, 3, 2, 1, 0, 0, '', 'Brann Bronzebeard gossip menu option - Show only if DATA_VAULT_OF_LIGHTS is not done'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=77437; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13, 6, 77437, 0, 0, 31, 0, 3, 39804, 0, 0, 0, 0, '', 'Destruction Protocol - Stone Trogg Pillager'), +(13, 6, 77437, 0, 1, 31, 0, 3, 40252, 0, 0, 0, 0, '', 'Destruction Protocol - Stone Trogg Rock Flinger'), +(13, 6, 77437, 0, 2, 31, 0, 3, 40251, 0, 0, 0, 0, '', 'Destruction Protocol - Stone Trogg Brute'); + +UPDATE `creature_template` SET `ScriptName`='npc_alpha_beam' WHERE `entry`=41144; +UPDATE `creature_template` SET `ScriptName`='npc_omega_stance' WHERE `entry`=41194; + +DELETE FROM `spell_script_names` WHERE `spell_id`=94974; diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index 33fd43a86d5..570fe23478f 100644 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -331,6 +331,7 @@ void AddSC_instance_zulfarrak(); //Zul'Farrak instance script void AddSC_instance_halls_of_origination(); void AddSC_boss_temple_guardian_anhuur(); void AddSC_boss_earthrager_ptah(); +void AddSC_boss_anraphet(); void AddSC_ashenvale(); void AddSC_azshara(); @@ -989,6 +990,7 @@ void AddKalimdorScripts() AddSC_instance_halls_of_origination(); AddSC_boss_temple_guardian_anhuur(); AddSC_boss_earthrager_ptah(); + AddSC_boss_anraphet(); #endif } diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index d05fb243fa2..69270c1ed4b 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3624,11 +3624,6 @@ void SpellMgr::LoadSpellInfoCorrections() // Aura is refreshed at 3 seconds, and the tick should happen at the fourth. spellInfo->AttributesEx8 |= SPELL_ATTR8_DONT_RESET_PERIODIC_TIMER; break; - // Earthrager Ptah - case 94974: - // Hacked as a timed event until SPELL_EFFECT_TRIGGER_MISSILE is correctly fixed. - spellInfo->Effects[EFFECT_0].TriggerSpell = 0; - break; default: break; } diff --git a/src/server/scripts/Kalimdor/CMakeLists.txt b/src/server/scripts/Kalimdor/CMakeLists.txt index 4c22cdd080b..fc75444bda6 100644 --- a/src/server/scripts/Kalimdor/CMakeLists.txt +++ b/src/server/scripts/Kalimdor/CMakeLists.txt @@ -115,6 +115,7 @@ set(scripts_STAT_SRCS Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp Kalimdor/HallsOfOrigination/boss_earthrager_ptah.cpp + Kalimdor/HallsOfOrigination/boss_anraphet.cpp ) message(" -> Prepared: Kalimdor") diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp new file mode 100644 index 00000000000..490c0a77494 --- /dev/null +++ b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp @@ -0,0 +1,571 @@ +/* + * Copyright (C) 2008-2012 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/>. + */ + +#include "ObjectMgr.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" +#include "GridNotifiers.h" +#include "Player.h" +#include "ObjectAccessor.h" +#include "halls_of_origination.h" + +enum Texts +{ + ANRAPHET_SAY_INTRO = 0, + ANRAPHET_SAY_AGGRO = 1, + ANRAPHET_SAY_OMEGA_STANCE = 2, + ANRAPHET_SAY_KILL = 3, + ANRAPHET_SAY_DEATH = 4, + + BRANN_SAY_DOOR_INTRO = 0, // Right, let's go! Just need to input the final entry sequence into the door mechanism... and... + BRANN_SAY_UNLOCK_DOOR = 1, // That did the trick! The control room should be right behind this... oh... wow... + BRANN_SAY_TROGGS = 2, // What? This isn't the control room! There's another entire defense mechanism in place, and the blasted Rock Troggs broke into here somehow. Troggs. Why did it have to be Troggs! + BRANN_SAY_THINK = 3, // Ok, let me think a moment. + BRANN_SAY_MIRRORS = 4, // Mirrors pointing all over the place. + BRANN_SAY_ELEMENTALS = 5, // Four platforms with huge elementals. + BRANN_SAY_GET_IT = 6, // I got it! I saw a tablet that mentioned this chamber. This is the Vault of Lights! Ok, simple enough. I need you adventurers to take out each of the four elementals to trigger the opening sequence for the far door! + BRANN_1_ELEMENTAL_DEAD = 7, // One down! + BRANN_2_ELEMENTAL_DEAD = 8, // Another one down! Just look at those light beams! They seem to be connecting to the far door! + BRANN_3_ELEMENTAL_DEAD = 9, // One more elemental to go! The door is almost open! + BRANN_4_ELEMENTAL_DEAD = 10, // That''s it, you''ve done it! The vault door is opening! Now we can... oh, no! + BRANN_SAY_ANRAPHET_DIED = 11, // We''ve done it! The control room is breached! + BRANN_SAY_MOMENT = 12 // Here we go! Now this should only take a moment... +}; + +enum Events +{ + EVENT_BRANN_MOVE_INTRO = 1, + EVENT_BRANN_UNLOCK_DOOR = 2, + EVENT_BRANN_THINK = 3, + EVENT_BRANN_SET_ORIENTATION_1 = 4, + EVENT_BRANN_SET_ORIENTATION_2 = 5, + EVENT_BRANN_SET_ORIENTATION_3 = 6, + EVENT_BRANN_SAY_ELEMENTALS = 7, + EVENT_BRANN_SAY_GET_IT = 8, + EVENT_BRANN_SET_ORIENTATION_4 = 9, + + EVENT_ANRAPHET_APPEAR = 10, + EVENT_ANRAPHET_ACTIVATE = 11, + EVENT_ANRAPHET_DESTROY = 12, + EVENT_ANRAPHET_READY = 13, + EVENT_ANRAPHET_NEMESIS_STRIKE = 14, + EVENT_ANRAPHET_ALPHA_BEAMS = 15, + EVENT_ANRAPHET_OMEGA_STANCE = 16, + EVENT_ANRAPHET_CRUMBLING_RUIN = 17, + EVENT_ANRAPHET_ACTIVATE_OMEGA = 18 +}; + +enum Spells +{ + SPELL_DESTRUCTION_PROTOCOL = 77437, + + SPELL_ALPHA_BEAMS = 76184, + SPELL_ALPHA_BEAMS_BACK_CAST = 76912, + + SPELL_CRUMBLING_RUIN = 75609, + + + SPELL_NEMESIS_STRIKE = 75604, + + SPELL_OMEGA_STANCE_SUMMON = 77106, + SPELL_OMEGA_STANCE = 75622, + SPELL_OMEGA_STANCE_SPIDER_TRIGGER = 77121, +}; + +enum Phases +{ + PHASE_INTRO = 1, + PHASE_COMBAT = 2, + + PHASE_MASK_COMBAT = (1 << PHASE_COMBAT), +}; + +enum Points +{ + POINT_ANRAPHET_ACTIVATE = 0, + MAX_BRANN_WAYPOINTS_INTRO = 17 +}; + +Position const AnraphetActivatePos = {-193.656f, 366.689f, 75.91001f, 3.138207f}; + +Position const BrannIntroWaypoint[MAX_BRANN_WAYPOINTS_INTRO] = +{ + {-429.583f, 367.019f, 89.79282f, 0.0f}, + {-409.9531f, 367.0469f, 89.81111f, 0.0f}, + {-397.8246f, 366.967f, 86.37722f, 0.0f}, + {-383.7813f, 366.8229f, 82.07919f, 0.0f}, + {-368.2604f, 366.7448f, 77.0984f, 0.0f}, + {-353.6458f, 366.4896f, 75.92504f, 0.0f}, + {-309.0608f, 366.7205f, 75.91345f, 0.0f}, + {-276.3303f, 367.0f, 75.92413f, 0.0f}, + {-246.5104f, 366.6389f, 75.87791f, 0.0f}, + {-202.0417f, 366.7517f, 75.92508f, 0.0f}, + {-187.6024f, 366.7656f, 76.23077f, 0.0f}, + {-155.0938f, 366.783f, 86.45834f, 0.0f}, + {-143.5694f, 366.8177f, 89.73354f, 0.0f}, + {-128.5608f, 366.8629f, 89.74199f, 0.0f}, + {-103.559f, 366.5938f, 89.79725f, 0.0f}, + {-71.58507f, 367.0278f, 89.77069f, 0.0f}, + {-35.04861f, 366.6563f, 89.77447f, 0.0f}, +}; + +class boss_anraphet : public CreatureScript +{ +public: + boss_anraphet() : CreatureScript("boss_anraphet") { } + + struct boss_anraphetAI : public BossAI + { + boss_anraphetAI(Creature* creature) : BossAI(creature, DATA_ANRAPHET) { } + + void ScheduleCombatEvents() + { + events.ScheduleEvent(EVENT_ANRAPHET_NEMESIS_STRIKE, 8000, 0, PHASE_COMBAT); + events.ScheduleEvent(EVENT_ANRAPHET_ALPHA_BEAMS, 10000, 0, PHASE_COMBAT); + events.ScheduleEvent(EVENT_ANRAPHET_OMEGA_STANCE, 35000, 0, PHASE_COMBAT); + } + + void Reset() + { + _Reset(); + me->SetWalk(false); + events.SetPhase(PHASE_INTRO); + if (instance->GetData(DATA_DEAD_ELEMENTALS) == 4) + { + // Set to combat automatically, Brann's event won't repeat + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + events.SetPhase(PHASE_COMBAT); + ScheduleCombatEvents(); + me->SetHomePosition(AnraphetActivatePos); + } + } + + void EnterCombat(Unit* /*who*/) + { + instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1); + Talk(ANRAPHET_SAY_AGGRO); + _EnterCombat(); + } + + void JustDied(Unit* /*killer*/) + { + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + Talk(ANRAPHET_SAY_DEATH); + + if (Creature* brann = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_BRANN_0_GUID))) + brann->AI()->DoAction(ACTION_ANRAPHET_DIED); + + _JustDied(); + } + + void KilledUnit(Unit* victim) + { + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(ANRAPHET_SAY_KILL); + } + + void JustReachedHome() + { + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + _JustReachedHome(); + instance->SetBossState(DATA_ANRAPHET, FAIL); + } + + void DoAction(int32 const action) + { + if (action == ACTION_ANRAPHET_INTRO) + events.ScheduleEvent(EVENT_ANRAPHET_APPEAR, 6000, 0, PHASE_INTRO); + } + + void MovementInform(uint32 type, uint32 point) + { + if (type != POINT_MOTION_TYPE) + return; + + if (point == POINT_ANRAPHET_ACTIVATE) + { + events.ScheduleEvent(EVENT_ANRAPHET_ACTIVATE, 1500, 0, PHASE_INTRO); + me->SetHomePosition(AnraphetActivatePos); + } + } + + void UpdateAI(uint32 const diff) + { + if ((events.GetPhaseMask() & PHASE_MASK_COMBAT) && (!UpdateVictim() || !CheckInRoom())) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_ANRAPHET_APPEAR: + me->SetWalk(true); + me->GetMotionMaster()->MovePoint(POINT_ANRAPHET_ACTIVATE, AnraphetActivatePos); + break; + case EVENT_ANRAPHET_ACTIVATE: + me->SetWalk(false); + Talk(ANRAPHET_SAY_INTRO); + events.ScheduleEvent(EVENT_ANRAPHET_DESTROY, 17500, 0, PHASE_INTRO); + return; + case EVENT_ANRAPHET_DESTROY: + DoCastAOE(SPELL_DESTRUCTION_PROTOCOL); + events.ScheduleEvent(EVENT_ANRAPHET_READY, 6000, 0, PHASE_INTRO); + break; + case EVENT_ANRAPHET_READY: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + events.SetPhase(PHASE_COMBAT); + ScheduleCombatEvents(); + break; + case EVENT_ANRAPHET_NEMESIS_STRIKE: + DoCastVictim(SPELL_NEMESIS_STRIKE); + events.ScheduleEvent(EVENT_ANRAPHET_NEMESIS_STRIKE, 21500, 0, PHASE_COMBAT); + break; + case EVENT_ANRAPHET_ALPHA_BEAMS: + DoCast(me, SPELL_ALPHA_BEAMS); + events.ScheduleEvent(EVENT_ANRAPHET_CRUMBLING_RUIN, 12500, 0, PHASE_COMBAT); + events.ScheduleEvent(EVENT_ANRAPHET_ALPHA_BEAMS, urand(40000, 45000), 0, PHASE_COMBAT); + break; + case EVENT_ANRAPHET_OMEGA_STANCE: + DoCast(me, SPELL_OMEGA_STANCE_SUMMON); + DoCast(me, SPELL_OMEGA_STANCE); + Talk(ANRAPHET_SAY_OMEGA_STANCE); + events.ScheduleEvent(EVENT_ANRAPHET_OMEGA_STANCE, urand(45000, 50000), 0, PHASE_COMBAT); + events.ScheduleEvent(EVENT_ANRAPHET_CRUMBLING_RUIN, 13000, 0, PHASE_COMBAT); + break; + case EVENT_ANRAPHET_CRUMBLING_RUIN: + DoCast(me, SPELL_CRUMBLING_RUIN); + break; + } + } + + if (events.GetPhaseMask() & PHASE_MASK_COMBAT) + DoMeleeAttackIfReady(); + } + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetHallsOfOriginationAI<boss_anraphetAI>(creature); + } +}; + +class npc_omega_stance : public CreatureScript +{ + public: + npc_omega_stance() : CreatureScript("npc_omega_stance") { } + + struct npc_omega_stanceAI : public ScriptedAI + { + npc_omega_stanceAI(Creature* creature) : ScriptedAI(creature) { } + + void IsSummonedBy(Unit* /*who*/) + { + DoCast(me, SPELL_OMEGA_STANCE_SPIDER_TRIGGER, true); + } + + void EnterEvadeMode() { } + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_omega_stanceAI(creature); + } +}; + +class npc_alpha_beam : public CreatureScript +{ + public: + npc_alpha_beam() : CreatureScript("npc_alpha_beam") { } + + struct npc_alpha_beamAI : public ScriptedAI + { + npc_alpha_beamAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } + + void IsSummonedBy(Unit* summoner) + { + if (Creature* anraphet = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_ANRAPHET_GUID))) + anraphet->CastSpell(me, SPELL_ALPHA_BEAMS_BACK_CAST); + } + + void EnterEvadeMode() { } // Never evade + + private: + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetHallsOfOriginationAI<npc_alpha_beamAI>(creature); + } +}; + +class npc_brann_bronzebeard_anraphet : public CreatureScript +{ + public: + npc_brann_bronzebeard_anraphet() : CreatureScript("npc_brann_bronzebeard_anraphet") { } + + struct npc_brann_bronzebeard_anraphetAI : public CreatureAI + { + npc_brann_bronzebeard_anraphetAI(Creature* creature) : CreatureAI(creature), _currentPoint(0), _instance(creature->GetInstanceScript()) { } + + void sGossipSelect(Player* /*player*/, uint32 sender, uint32 action) + { + if (_instance->GetBossState(DATA_VAULT_OF_LIGHTS) == DONE) + return; + + if (me->GetCreatureTemplate()->GossipMenuId == sender && !action) + { + _instance->SetBossState(DATA_VAULT_OF_LIGHTS, IN_PROGRESS); + _currentPoint = 0; + events.Reset(); + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + me->SetWalk(true); + Talk(BRANN_SAY_DOOR_INTRO); + events.ScheduleEvent(EVENT_BRANN_UNLOCK_DOOR, 7500); + } + } + + void DoAction(int32 const action) + { + switch (action) + { + case ACTION_ELEMENTAL_DIED: + { + uint32 dead = _instance->GetData(DATA_DEAD_ELEMENTALS); + Talk(BRANN_1_ELEMENTAL_DEAD + dead - 1); + if (dead == 4) + { + _instance->DoCastSpellOnPlayers(SPELL_VAULT_OF_LIGHTS_CREDIT); + if (Creature* anraphet = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_ANRAPHET_GUID))) + anraphet->AI()->DoAction(ACTION_ANRAPHET_INTRO); + } + break; + } + case ACTION_ANRAPHET_DIED: + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, 1000); + break; + } + } + + void UpdateAI(uint32 const diff) + { + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_BRANN_MOVE_INTRO: + if (_currentPoint < MAX_BRANN_WAYPOINTS_INTRO) + me->GetMotionMaster()->MovePoint(_currentPoint, BrannIntroWaypoint[_currentPoint]); + break; + case EVENT_BRANN_UNLOCK_DOOR: + Talk(BRANN_SAY_UNLOCK_DOOR); + _instance->SetBossState(DATA_VAULT_OF_LIGHTS, DONE); + _instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_VAULT_OF_LIGHTS_EVENT); + events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, 3500); + break; + case EVENT_BRANN_THINK: + Talk(BRANN_SAY_THINK); + events.ScheduleEvent(EVENT_BRANN_SET_ORIENTATION_1, 6000); + break; + case EVENT_BRANN_SET_ORIENTATION_1: + me->SetFacingTo(5.445427f); + Talk(BRANN_SAY_MIRRORS); + events.ScheduleEvent(EVENT_BRANN_SET_ORIENTATION_2, 1000); + break; + case EVENT_BRANN_SET_ORIENTATION_2: + me->SetFacingTo(0.6283185f); + events.ScheduleEvent(EVENT_BRANN_SET_ORIENTATION_3, 2500); + break; + case EVENT_BRANN_SET_ORIENTATION_3: + me->SetFacingTo(0.01745329f); + events.ScheduleEvent(EVENT_BRANN_SAY_ELEMENTALS, 200); + break; + case EVENT_BRANN_SAY_ELEMENTALS: + Talk(BRANN_SAY_ELEMENTALS); + events.ScheduleEvent(EVENT_BRANN_SAY_GET_IT, 3500); + break; + case EVENT_BRANN_SAY_GET_IT: + Talk(BRANN_SAY_GET_IT); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + break; + case EVENT_BRANN_SET_ORIENTATION_4: + me->SetFacingTo(3.141593f); + break; + } + } + } + + void MovementInform(uint32 movementType, uint32 pointId) + { + if (movementType != POINT_MOTION_TYPE) + return; + + _currentPoint = pointId + 1; + uint32 delay = 1; + + switch (pointId) + { + case 0: + Talk(BRANN_SAY_TROGGS); + events.ScheduleEvent(EVENT_BRANN_THINK, 15000); + return; + case 1: + Talk(BRANN_SAY_ANRAPHET_DIED); + delay = 1000; + break; + case 14: + Talk(BRANN_SAY_MOMENT); + delay = 2200; + break; + case 16: + events.ScheduleEvent(EVENT_BRANN_SET_ORIENTATION_4, 6000); + return; + default: + break; + } + + events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, delay); + } + + protected: + EventMap events; + uint32 _currentPoint; + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetHallsOfOriginationAI<npc_brann_bronzebeard_anraphetAI>(creature); + } +}; + +class spell_anraphet_alpha_beams : public SpellScriptLoader +{ +public: + spell_anraphet_alpha_beams() : SpellScriptLoader("spell_anraphet_alpha_beams") { } + + class spell_anraphet_alpha_beams_SpellScript : public SpellScript + { + PrepareSpellScript(spell_anraphet_alpha_beams_SpellScript); + + void FilterTargets(std::list<WorldObject*>& targets) + { + if (targets.empty()) + return; + + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(target); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_anraphet_alpha_beams_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_anraphet_alpha_beams_SpellScript(); + } +}; + +class spell_anraphet_omega_stance_summon : public SpellScriptLoader +{ +public: + spell_anraphet_omega_stance_summon() : SpellScriptLoader("spell_anraphet_omega_stance_summon") { } + + class spell_anraphet_omega_stance_summon_SpellScript : public SpellScript + { + PrepareSpellScript(spell_anraphet_omega_stance_summon_SpellScript); + + void ModDestHeight(SpellEffIndex /*effIndex*/) + { + Position offset = {0.0f, 0.0f, 30.0f, 0.0f}; + const_cast<WorldLocation*>(GetExplTargetDest())->RelocateOffset(offset); + GetHitDest()->RelocateOffset(offset); + } + + void Register() + { + OnEffectLaunch += SpellEffectFn(spell_anraphet_omega_stance_summon_SpellScript::ModDestHeight, EFFECT_0, SPELL_EFFECT_SUMMON); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_anraphet_omega_stance_summon_SpellScript(); + } +}; + +class spell_omega_stance_spider_effect : public SpellScriptLoader +{ +public: + spell_omega_stance_spider_effect() : SpellScriptLoader("spell_omega_stance_spider_effect") { } + + class spell_omega_stance_spider_effect_SpellScript : public SpellScript + { + PrepareSpellScript(spell_omega_stance_spider_effect_SpellScript); + + void SetDestPosition(SpellEffIndex effIndex) + { + // Do our own calculations for the destination position. + /// TODO: Remove this once we find a general rule for WorldObject::MovePosition (this spell shouldn't take the Z change into consideration) + Unit* caster = GetCaster(); + float angle = float(rand_norm()) * static_cast<float>(2 * M_PI); + uint32 dist = caster->GetObjectSize() + GetSpellInfo()->Effects[effIndex].CalcRadius(GetCaster()) * (float)rand_norm(); + + float x = caster->GetPositionX() + dist * std::cos(angle); + float y = caster->GetPositionY() + dist * std::sin(angle); + float z = caster->GetMap()->GetHeight(x, y, caster->GetPositionZ()); + + const_cast<WorldLocation*>(GetExplTargetDest())->Relocate(x, y, z); + GetHitDest()->Relocate(x, y, z); + } + + void Register() + { + OnEffectLaunch += SpellEffectFn(spell_omega_stance_spider_effect_SpellScript::SetDestPosition, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_omega_stance_spider_effect_SpellScript(); + } +}; + +void AddSC_boss_anraphet() +{ + new boss_anraphet(); + new spell_anraphet_alpha_beams(); + new npc_brann_bronzebeard_anraphet(); + new npc_alpha_beam(); + new spell_anraphet_omega_stance_summon(); + new spell_omega_stance_spider_effect(); + new npc_omega_stance(); +} diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_earthrager_ptah.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_earthrager_ptah.cpp index cba0ea0b61c..e20ad0ccf82 100644 --- a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_earthrager_ptah.cpp +++ b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_earthrager_ptah.cpp @@ -45,7 +45,6 @@ enum Spells SPELL_RAGING_SMASH = 83650, SPELL_FLAME_BOLT = 77370, SPELL_EARTH_SPIKE_WARN = 94974, - SPELL_EARTH_SPIKE_ERUPT = 75339, SPELL_PTAH_EXPLOSION = 75519, SPELL_SANDSTORM = 75491, @@ -91,22 +90,6 @@ protected: Unit* _owner; }; -class EruptEarthSpike : public BasicEvent -{ -public: - EruptEarthSpike(Unit* caster, WorldLocation const target) : _caster(caster), _target(target) { } - - bool Execute(uint64 execTime, uint32 /*diff*/) - { - _caster->CastSpell(_target.GetPositionX(), _target.GetPositionY(), _target.GetPositionZ(), SPELL_EARTH_SPIKE_ERUPT, true); - return true; - } - -protected: - Unit* _caster; - WorldLocation const _target; -}; - class boss_earthrager_ptah : public CreatureScript { public: @@ -315,34 +298,6 @@ class spell_earthrager_ptah_flame_bolt : public SpellScriptLoader } }; -class spell_earthrager_ptah_earth_spike : public SpellScriptLoader -{ -public: - spell_earthrager_ptah_earth_spike() : SpellScriptLoader("spell_earthrager_ptah_earth_spike") { } - - class spell_earthrager_ptah_earth_spike_SpellScript : public SpellScript - { - PrepareSpellScript(spell_earthrager_ptah_earth_spike_SpellScript); - - void Launch(SpellEffIndex index) - { - PreventHitDefaultEffect(index); - // Erupt the spike in 4 seconds. - GetCaster()->m_Events.AddEvent(new EruptEarthSpike(GetCaster(), *GetExplTargetDest()), GetCaster()->m_Events.CalculateTime(4000)); - } - - void Register() - { - OnEffectHit += SpellEffectFn(spell_earthrager_ptah_earth_spike_SpellScript::Launch, EFFECT_0, SPELL_EFFECT_TRIGGER_MISSILE); - } - }; - - SpellScript* GetSpellScript() const - { - return new spell_earthrager_ptah_earth_spike_SpellScript(); - } -}; - class spell_earthrager_ptah_explosion : public SpellScriptLoader { public: @@ -387,6 +342,5 @@ void AddSC_boss_earthrager_ptah() { new boss_earthrager_ptah(); new spell_earthrager_ptah_flame_bolt(); - new spell_earthrager_ptah_earth_spike(); new spell_earthrager_ptah_explosion(); } diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.h b/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.h index 3258df45a0b..54ecdfb331d 100644 --- a/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.h +++ b/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.h @@ -20,13 +20,18 @@ #define HoOScriptName "instance_halls_of_origination" -uint32 const EncounterCount = 7; +uint32 const EncounterCount = 12; enum Data { // Bosses DATA_TEMPLE_GUARDIAN_ANHUUR, DATA_EARTHRAGER_PTAH, + DATA_VAULT_OF_LIGHTS, + DATA_FIRE_WARDEN, + DATA_EARTH_WARDEN, + DATA_WATER_WARDEN, + DATA_AIR_WARDEN, DATA_ANRAPHET, DATA_ISISET, DATA_AMMUNAE, @@ -39,6 +44,11 @@ enum Data DATA_ANHUUR_RIGHT_BEACON, DATA_ANHUUR_BRIDGE, DATA_ANHUUR_DOOR, + + // Anraphet + DATA_BRANN_0_GUID, + DATA_DEAD_ELEMENTALS, + DATA_ANRAPHET_GUID, }; enum Creatures @@ -52,6 +62,17 @@ enum Creatures NPC_JEWELED_SCARAB = 40458, NPC_DUSTBONE_HORROR = 40450, NPC_QUICKSAND = 40503, // Summoned by a spell not in dbc (75550) + + BOSS_ANRAPHET = 39788, + NPC_FIRE_WARDEN = 39800, + NPC_EARTH_WARDEN = 39801, + NPC_WATER_WARDEN = 39802, + NPC_AIR_WARDEN = 39803, + + WARDEN_ENTRY_DATA_DELTA = NPC_FIRE_WARDEN - DATA_FIRE_WARDEN, + + NPC_BRANN_BRONZEBEARD_0 = 39908, + NPC_OMEGA_STANCE = 41194, }; enum GameObjects @@ -61,11 +82,35 @@ enum GameObjects GO_ANHUURS_DOOR = 202307, GO_ANHUURS_RIGHT_BEACON = 203136, GO_ANHUURS_LEFT_BEACON = 203133, + + GO_VAULT_OF_LIGHTS_DOOR = 202313, + GO_SUN_MIRROR = 207726, + GO_ANRAPHET_DOOR = 202314, + + GO_DOODAD_ULDUM_LIGHTMACHINE_01 = 207375, + GO_DOODAD_ULDUM_LIGHTMACHINE_02 = 207374, + GO_DOODAD_ULDUM_LIGHTMACHINE_03 = 207377, + GO_DOODAD_ULDUM_LIGHTMACHINE_04 = 207376, + + GO_DOODAD_ULDUM_LASERBEAMS01 = 207662, // Matches GO_DOODAD_ULDUM_LIGHTMACHINE_02 + GO_DOODAD_ULDUM_LASERBEAMS_01 = 207663, // Matches GO_DOODAD_ULDUM_LIGHTMACHINE_01 + GO_DOODAD_ULDUM_LASERBEAMS_02 = 207664, // Matches GO_DOODAD_ULDUM_LIGHTMACHINE_04 + GO_DOODAD_ULDUM_LASERBEAMS_03 = 207665, // Matches GO_DOODAD_ULDUM_LIGHTMACHINE_03 }; -enum AreaIds +enum Misc { AREA_TOMB_OF_THE_EARTHRAGER = 5610, + ACHIEV_VAULT_OF_LIGHTS_EVENT = 24212, // Faster Than The Speed Of Light + SPELL_VAULT_OF_LIGHTS_CREDIT = 94067, // Not in DBC +}; + +enum GlobalActions +{ + ACTION_ANRAPHET_INTRO, + ACTION_ELEMENTAL_DIED, + ACTION_ANRAPHET_DIED, + ACTION_OMEGA_TRIGGER, }; template<class AI> diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp index e5ef556003f..0cb21aeeba1 100644 --- a/src/server/scripts/Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp +++ b/src/server/scripts/Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp @@ -29,10 +29,19 @@ DoorData const doorData[] = { - {GO_ANHUURS_DOOR, DATA_TEMPLE_GUARDIAN_ANHUUR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - {GO_ANHUURS_BRIDGE, DATA_TEMPLE_GUARDIAN_ANHUUR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - {GO_DOODAD_ULDUM_ELEVATOR_COL01, DATA_TEMPLE_GUARDIAN_ANHUUR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } + {GO_ANHUURS_DOOR, DATA_TEMPLE_GUARDIAN_ANHUUR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + {GO_ANHUURS_BRIDGE, DATA_TEMPLE_GUARDIAN_ANHUUR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + {GO_DOODAD_ULDUM_ELEVATOR_COL01, DATA_TEMPLE_GUARDIAN_ANHUUR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + {GO_VAULT_OF_LIGHTS_DOOR, DATA_VAULT_OF_LIGHTS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + {GO_DOODAD_ULDUM_LIGHTMACHINE_02, DATA_EARTH_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + {GO_DOODAD_ULDUM_LASERBEAMS01, DATA_EARTH_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + {GO_DOODAD_ULDUM_LIGHTMACHINE_01, DATA_FIRE_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + {GO_DOODAD_ULDUM_LASERBEAMS_01, DATA_FIRE_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + {GO_DOODAD_ULDUM_LIGHTMACHINE_03, DATA_WATER_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + {GO_DOODAD_ULDUM_LASERBEAMS_03, DATA_WATER_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + {GO_DOODAD_ULDUM_LIGHTMACHINE_04, DATA_AIR_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + {GO_DOODAD_ULDUM_LASERBEAMS_02, DATA_AIR_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } }; class instance_halls_of_origination : public InstanceMapScript @@ -51,6 +60,11 @@ class instance_halls_of_origination : public InstanceMapScript AnhuursDoorGUID = 0; AnhuurRightBeaconGUID = 0; AnhuurLeftBeaconGUID = 0; + BrannBronzebeardGUID = 0; + AnraphetGUID = 0; + AnraphetDoorGUID = 0; + SunMirrorGUID = 0; + _deadElementals = 0; } void OnGameObjectCreate(GameObject* go) @@ -60,6 +74,15 @@ class instance_halls_of_origination : public InstanceMapScript case GO_ANHUURS_BRIDGE: AnhuursBridgeGUID = go->GetGUID(); case GO_DOODAD_ULDUM_ELEVATOR_COL01: + case GO_VAULT_OF_LIGHTS_DOOR: + case GO_DOODAD_ULDUM_LIGHTMACHINE_01: + case GO_DOODAD_ULDUM_LIGHTMACHINE_02: + case GO_DOODAD_ULDUM_LIGHTMACHINE_03: + case GO_DOODAD_ULDUM_LIGHTMACHINE_04: + case GO_DOODAD_ULDUM_LASERBEAMS01: + case GO_DOODAD_ULDUM_LASERBEAMS_01: + case GO_DOODAD_ULDUM_LASERBEAMS_02: + case GO_DOODAD_ULDUM_LASERBEAMS_03: AddDoor(go, true); break; case GO_ANHUURS_DOOR: @@ -72,6 +95,12 @@ class instance_halls_of_origination : public InstanceMapScript case GO_ANHUURS_LEFT_BEACON: AnhuurLeftBeaconGUID = go->GetGUID(); break; + case GO_SUN_MIRROR: + SunMirrorGUID = go->GetGUID(); + break; + case GO_ANRAPHET_DOOR: + AnraphetDoorGUID = go->GetGUID(); + break; } } @@ -82,6 +111,15 @@ class instance_halls_of_origination : public InstanceMapScript case GO_ANHUURS_BRIDGE: case GO_DOODAD_ULDUM_ELEVATOR_COL01: case GO_ANHUURS_DOOR: + case GO_VAULT_OF_LIGHTS_DOOR: + case GO_DOODAD_ULDUM_LIGHTMACHINE_01: + case GO_DOODAD_ULDUM_LIGHTMACHINE_02: + case GO_DOODAD_ULDUM_LIGHTMACHINE_03: + case GO_DOODAD_ULDUM_LIGHTMACHINE_04: + case GO_DOODAD_ULDUM_LASERBEAMS01: + case GO_DOODAD_ULDUM_LASERBEAMS_01: + case GO_DOODAD_ULDUM_LASERBEAMS_02: + case GO_DOODAD_ULDUM_LASERBEAMS_03: AddDoor(go, false); break; } @@ -94,9 +132,28 @@ class instance_halls_of_origination : public InstanceMapScript case BOSS_TEMPLE_GUARDIAN_ANHUUR: TempleGuardianAnhuurGUID = creature->GetGUID(); break; + case NPC_BRANN_BRONZEBEARD_0: + BrannBronzebeardGUID = creature->GetGUID(); + break; + case BOSS_ANRAPHET: + AnraphetGUID = creature->GetGUID(); + break; } } + uint32 GetData(uint32 data) const + { + switch (data) + { + case DATA_DEAD_ELEMENTALS: + return _deadElementals; + default: + break; + } + + return 0; + } + uint64 GetData64(uint32 index) const { switch (index) @@ -111,17 +168,55 @@ class instance_halls_of_origination : public InstanceMapScript return AnhuurRightBeaconGUID; case DATA_ANHUUR_GUID: return TempleGuardianAnhuurGUID; + case DATA_BRANN_0_GUID: + return BrannBronzebeardGUID; + case DATA_ANRAPHET_GUID: + return AnraphetGUID; } return 0; } + void IncreaseDeadElementals(uint32 inc) + { + _deadElementals += inc; + if (_deadElementals == 4) + { + if (GameObject* mirror = instance->GetGameObject(SunMirrorGUID)) + mirror->SetGoState(GO_STATE_ACTIVE); + if (GameObject* door = instance->GetGameObject(AnraphetDoorGUID)) + door->SetGoState(GO_STATE_ACTIVE); + } + } + + void OnUnitDeath(Unit* unit) + { + Creature* creature = unit->ToCreature(); + if (!creature) + return; + + switch (creature->GetEntry()) + { + case NPC_FIRE_WARDEN: + case NPC_EARTH_WARDEN: + case NPC_WATER_WARDEN: + case NPC_AIR_WARDEN: + uint32 data = creature->GetEntry() - WARDEN_ENTRY_DATA_DELTA; + SetBossState(data, IN_PROGRESS); // Needs to be set to IN_PROGRESS or else the gameobjects state won't be updated + SetBossState(data, DONE); + IncreaseDeadElementals(1); + if (Creature* brann = instance->GetCreature(BrannBronzebeardGUID)) + brann->AI()->DoAction(ACTION_ELEMENTAL_DIED); + break; + } + } + std::string GetSaveData() { OUT_SAVE_INST_DATA; std::ostringstream saveStream; - saveStream << "H O " << GetBossSaveData(); + saveStream << "H O " << GetBossSaveData() << _deadElementals; OUT_SAVE_INST_DATA_COMPLETE; return saveStream.str(); @@ -152,6 +247,9 @@ class instance_halls_of_origination : public InstanceMapScript tmpState = NOT_STARTED; SetBossState(i, EncounterState(tmpState)); } + uint32 tmp; + loadStream >> tmp; + IncreaseDeadElementals(tmp); } else OUT_LOAD_INST_DATA_FAIL; @@ -165,6 +263,11 @@ class instance_halls_of_origination : public InstanceMapScript uint64 AnhuursDoorGUID; uint64 AnhuurRightBeaconGUID; uint64 AnhuurLeftBeaconGUID; + uint64 BrannBronzebeardGUID; + uint64 AnraphetGUID; + uint64 AnraphetDoorGUID; + uint64 SunMirrorGUID; + uint32 _deadElementals; }; InstanceScript* GetInstanceScript(InstanceMap* map) const |