diff options
-rw-r--r-- | src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp | 251 |
1 files changed, 104 insertions, 147 deletions
diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index 75c56a9d947..44dff329433 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -324,8 +324,10 @@ enum MiscData // Target guids DATA_LAST_OVERLOAD_GUID = 13, // used to store last Arcane Overload guid DATA_FIRST_SURGE_TARGET_GUID = 14, - DATA_SECOND_SURGE_TARGET_GUID = 15, - DATA_THIRD_SURGE_TARGET_GUID = 16 + //DATA_SECOND_SURGE_TARGET_GUID = 15, + //DATA_THIRD_SURGE_TARGET_GUID = 16 + + NUM_MAX_SURGE_TARGETS = 3, }; // Used to check if summons guids come from vehicles @@ -357,9 +359,7 @@ public: _summonDeaths = 0; _preparingPulsesChecker = 0; _arcaneOverloadGUID = NULL; - _firstSelectedSurgeTargetGUID = NULL; - _secondSelectedSurgeTargetGUID = NULL; - _thirdSelectedSurgeTargetGUID = NULL; + memset(_surgeTargetGUID, 0, sizeof(_surgeTargetGUID)); _killSpamFilter = false; _canAttack = false; @@ -421,17 +421,10 @@ public: } } - uint64 GetGUID(int32 data) const + uint64 GetGUID(int32 type) const { - switch (data) - { - case DATA_FIRST_SURGE_TARGET_GUID: - return _firstSelectedSurgeTargetGUID; - case DATA_SECOND_SURGE_TARGET_GUID: - return _secondSelectedSurgeTargetGUID; - case DATA_THIRD_SURGE_TARGET_GUID: - return _thirdSelectedSurgeTargetGUID; - } + if (type >= DATA_FIRST_SURGE_TARGET_GUID && type < DATA_FIRST_SURGE_TARGET_GUID + NUM_MAX_SURGE_TARGETS) + return _surgeTargetGUID[type - DATA_FIRST_SURGE_TARGET_GUID]; return 0; } @@ -444,13 +437,9 @@ public: _arcaneOverloadGUID = guid; break; case DATA_FIRST_SURGE_TARGET_GUID: - _firstSelectedSurgeTargetGUID = guid; - break; - case DATA_SECOND_SURGE_TARGET_GUID: - _secondSelectedSurgeTargetGUID = guid; - break; - case DATA_THIRD_SURGE_TARGET_GUID: - _thirdSelectedSurgeTargetGUID = guid; + case DATA_FIRST_SURGE_TARGET_GUID + 1: + case DATA_FIRST_SURGE_TARGET_GUID + 2: + _surgeTargetGUID[type - DATA_FIRST_SURGE_TARGET_GUID] = guid; break; } } @@ -954,22 +943,24 @@ public: case EVENT_SURGE_OF_POWER_P_THREE: if (GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) { - _tempSurgeTarget = NULL; - _drakeVehicle = NULL; - _playerSurgeTarget = NULL; - if ((_tempSurgeTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, false, SPELL_RIDE_RED_DRAGON_BUDDY))) - if ((_drakeVehicle = _tempSurgeTarget->GetVehicleKit())) - if ((_playerSurgeTarget = _drakeVehicle->GetPassenger(0)->ToPlayer())) + if (Unit* tempSurgeTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, false, SPELL_RIDE_RED_DRAGON_BUDDY)) + { + if (Vehicle* drakeVehicle = tempSurgeTarget->GetVehicleKit()) + { + if (Unit* passenger = drakeVehicle->GetPassenger(0)) { - Talk(EMOTE_SURGE_OF_POWER_WARNING_P3, _playerSurgeTarget->GetGUID()); - DoCast(_tempSurgeTarget, SPELL_SURGE_OF_POWER_PHASE_3_10); + if (passenger->GetTypeId() == TYPEID_PLAYER) + { + Talk(EMOTE_SURGE_OF_POWER_WARNING_P3, passenger->GetGUID()); + DoCast(tempSurgeTarget, SPELL_SURGE_OF_POWER_PHASE_3_10); + } } + } + } } else if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) { - _firstSelectedSurgeTargetGUID = NULL; - _secondSelectedSurgeTargetGUID = NULL; - _thirdSelectedSurgeTargetGUID = NULL; + memset(_surgeTargetGUID, 0, sizeof(_surgeTargetGUID)); DoCastAOE(SPELL_SURGE_OF_POWER_WARNING_SELECTOR_25); } @@ -1053,13 +1044,7 @@ public: uint8 _summonDeaths; // Keeps count of arcane trash. uint8 _preparingPulsesChecker; // In retail they use 2 preparing pulses with 7 sec CD, after they pass 2 seconds. uint64 _arcaneOverloadGUID; // Last Arcane Overload summoned to know to which should visual be cast to (the purple ball, not bubble). - uint64 _firstSelectedSurgeTargetGUID; // All these three are used to keep current tagets to which warning should be sent - uint64 _secondSelectedSurgeTargetGUID; // during Surge of Power 25 man, also they act as sent targets because of that mechanic. - uint64 _thirdSelectedSurgeTargetGUID; - - Unit* _tempSurgeTarget; // These three are used for 10 man Surge of Power targeting. - Vehicle* _drakeVehicle; - Player* _playerSurgeTarget; + uint64 _surgeTargetGUID[3]; // All these three are used to keep current tagets to which warning should be sent bool _killSpamFilter; // Prevent text spamming on killed player by helping implement a CD. bool _canAttack; // Used to control attacking (Move Chase not being applied after Stop Attack, only few times should act like this). @@ -1542,8 +1527,11 @@ public: void IsSummonedBy(Unit* summoner) { - if ((_malygos = summoner->ToCreature())) + if (Creature* creature = summoner->ToCreature()) + { + _malygos = creature; _malygos->AI()->SetGUID(me->GetGUID(), DATA_LAST_OVERLOAD_GUID); + } } void UpdateAI (uint32 /*diff*/) @@ -1598,8 +1586,11 @@ public: void IsSummonedBy(Unit* summoner) { _summoner = NULL; - if ((_summoner = summoner->ToPlayer())) + if (Player* player = summoner->ToPlayer()) + { + _summoner = player; _events.ScheduleEvent(EVENT_CAST_RIDE_SPELL, 2*IN_MILLISECONDS); + } } void UpdateAI(uint32 diff) @@ -1618,7 +1609,7 @@ public: } } - void PassengerBoarded(Unit* unit, int8 /*seat*/, bool apply) + void PassengerBoarded(Unit* /*unit*/, int8 /*seat*/, bool apply) { if (!apply) { @@ -1762,22 +1753,19 @@ class spell_malygos_random_portal : public SpellScriptLoader } }; -class isPlayerOnVehicleChecker +class IsCreatureVehicleCheck { public: - isPlayerOnVehicleChecker(Unit* source) : _source(source) { } + IsCreatureVehicleCheck() { } - bool operator()(WorldObject* unit) + bool operator()(WorldObject* obj) { - if (Unit* target = ObjectAccessor::GetUnit(*_source, unit->GetGUID())) - if (target->IsOnVehicle(target->GetVehicleBase())) + if (Unit* unit = obj->ToUnit()) + if (unit->GetTypeId() == TYPEID_UNIT && unit->GetVehicleKit()) return true; return false; } - - private: - Unit* _source; }; class spell_malygos_arcane_storm : public SpellScriptLoader @@ -1804,20 +1792,31 @@ class spell_malygos_arcane_storm : public SpellScriptLoader void FilterTargets(std::list<WorldObject*>& targets) { + if (targets.empty()) + return; + Creature* malygos = GetCaster()->ToCreature(); if (GetSpellInfo()->Id == SPELL_ARCANE_STORM_P_III) - targets.remove_if(isPlayerOnVehicleChecker(malygos)); - - if (!targets.empty()) + { + IsCreatureVehicleCheck check; + Trinity::Containers::RandomResizeList(targets, check, (malygos->GetMap()->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL ? 4 : 10)); + } + else Trinity::Containers::RandomResizeList(targets, (malygos->GetMap()->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL ? 4 : 10)); + } - for (std::list<WorldObject*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) - malygos->CastSpell((*itr)->ToUnit(), SPELL_ARCANE_STORM_EXTRA_VISUAL, true); + void HandleVisual() + { + if (!GetHitUnit()) + return; + + GetCaster()->CastSpell(GetHitUnit(), SPELL_ARCANE_STORM_EXTRA_VISUAL, true); } void Register() { OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_malygos_arcane_storm_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + AfterHit += SpellHitFn(spell_malygos_arcane_storm_SpellScript::HandleVisual); } }; @@ -2013,48 +2012,19 @@ class spell_nexus_lord_align_disk_aggro : public SpellScriptLoader class IsPlayerOnHoverDisk { public: - IsPlayerOnHoverDisk(Unit* source, bool isOnHoverDisk) : _source(source), _isOnHoverDisk(isOnHoverDisk) { } + IsPlayerOnHoverDisk(bool isOnHoverDisk) : _isOnHoverDisk(isOnHoverDisk) { } - bool operator()(WorldObject* unit) + bool operator()(WorldObject* obj) { - if (_isOnHoverDisk) - { - if (Unit* passenger = ObjectAccessor::GetUnit(*_source, unit->GetGUID())) - if (passenger->GetVehicleBase() && passenger->GetVehicleBase()->GetEntry() == NPC_HOVER_DISK_MELEE) - return true; - } - else if (!_isOnHoverDisk) - { - if (Unit* passenger = ObjectAccessor::GetUnit(*_source, unit->GetGUID())) - if (!passenger->GetVehicleBase()) - return true; - } + if (Unit* passenger = obj->ToUnit()) + if (passenger->GetVehicleBase() && passenger->GetVehicleBase()->GetEntry() == NPC_HOVER_DISK_MELEE) + return _isOnHoverDisk; - return false; - } - - private: - Unit* _source; - - bool _isOnHoverDisk; -}; - -class CheckUnitAura -{ - public: - CheckUnitAura(Unit* source) : _source(source) { } - - bool operator()(WorldObject* unit) - { - if (Unit* target = ObjectAccessor::GetUnit(*_source, unit->GetGUID())) - if (target->HasAura(SPELL_ARCANE_BARRAGE_DAMAGE)) - return true; - - return false; + return !_isOnHoverDisk; } private: - Unit* _source; + bool _isOnHoverDisk; }; class spell_scion_of_eternity_arcane_barrage : public SpellScriptLoader @@ -2076,20 +2046,21 @@ class spell_scion_of_eternity_arcane_barrage : public SpellScriptLoader if (targets.empty()) return; - Creature* caster = GetCaster()->ToCreature(); - for (std::list<WorldObject*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) - _playersWithoutDisk.push_back((*itr)); + // Remove players not on Hover Disk from second list + std::list<WorldObject*> playersWithoutDisk; + IsPlayerOnHoverDisk check(false); + for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) + if (check(*itr)) + playersWithoutDisk.push_back(*itr); - // Remove players not on Hover Disk from second list, // if it's empty than we can have player on Hover disk as target. - _playersWithoutDisk.remove_if(IsPlayerOnHoverDisk(caster, false)); - // Else if there are players on the ground we remove all from vehicles. - if (_playersWithoutDisk.empty()) - targets.remove_if(IsPlayerOnHoverDisk(caster, true)); + if (!playersWithoutDisk.empty()) + targets = playersWithoutDisk; + // Finally here we remove all targets that have been damaged by Arcane Barrage // and have 2 seconds long aura still lasting. Used to give healers some time. if (!targets.empty()) - targets.remove_if(CheckUnitAura(caster)); + targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_ARCANE_BARRAGE_DAMAGE)); } void TriggerDamageSpellFromPlayer() @@ -2105,8 +2076,6 @@ class spell_scion_of_eternity_arcane_barrage : public SpellScriptLoader OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_scion_of_eternity_arcane_barrage_SpellScript::FilterMeleeHoverDiskPassangers, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); OnHit += SpellHitFn(spell_scion_of_eternity_arcane_barrage_SpellScript::TriggerDamageSpellFromPlayer); } - - std::list<WorldObject*> _playersWithoutDisk; }; SpellScript* GetSpellScript() const @@ -2332,41 +2301,32 @@ class spell_malygos_surge_of_power_warning_selector_25 : public SpellScriptLoade void SendThreeTargets(std::list<WorldObject*>& targets) { + // This spell hits only vehicles (SMSG_SPELL_GO target) Creature* caster = GetCaster()->ToCreature(); - targets.remove_if(isPlayerOnVehicleChecker(caster)); + targets.remove_if(IsCreatureVehicleCheck()); if (targets.empty()) return; - for (std::list<WorldObject*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) - _filteredSelectedTargets.push_back((*itr)); - - if (_filteredSelectedTargets.empty()) - return; + // But in fact it selects 3 targets (SMSG_SPELL_GO target are not filtered) + std::list<WorldObject*> selectedTargets = targets; - uint8 guidDataSlot = 14; // SetGuid in Malygos AI is reserved for 14th, 15th and 16th Id for the three targets - Trinity::Containers::RandomResizeList(_filteredSelectedTargets, 3); - for (std::list<WorldObject*>::const_iterator itr = _filteredSelectedTargets.begin(); itr != _filteredSelectedTargets.end(); ++itr) + uint8 guidDataSlot = DATA_FIRST_SURGE_TARGET_GUID; // SetGuid in Malygos AI is reserved for 14th, 15th and 16th Id for the three targets + Trinity::Containers::RandomResizeList(selectedTargets, 3); + for (std::list<WorldObject*>::const_iterator itr = selectedTargets.begin(); itr != selectedTargets.end(); ++itr) { - caster->AI()->SetGUID((*itr)->GetGUID(), guidDataSlot++); - if (IS_VEHICLE_GUID((*itr)->GetGUID())) - { - if (Vehicle* tempVehicle = (*itr)->ToCreature()->GetVehicleKit()) - if (tempVehicle->GetPassenger(0)) - if (Player* tempPlayer = tempVehicle->GetPassenger(0)->ToPlayer()) - caster->AI()->Talk(EMOTE_SURGE_OF_POWER_WARNING_P3, tempPlayer->GetGUID()); - } - else if (IS_PLAYER_GUID((*itr)->GetGUID())) - { - caster->AI()->Talk(EMOTE_SURGE_OF_POWER_WARNING_P3, (*itr)->GetGUID()); - } + Creature* target = (*itr)->ToCreature(); + caster->AI()->SetGUID(target->GetGUID(), guidDataSlot++); + + if (Vehicle* vehicle = target->GetVehicleKit()) + if (Unit* passenger = vehicle->GetPassenger(0)) + if (passenger->GetTypeId() == TYPEID_PLAYER) + caster->AI()->Talk(EMOTE_SURGE_OF_POWER_WARNING_P3, passenger->GetGUID()); } } void ExecuteMainSpell() { - // We shouldn't cast stuff from target selector hooks - Creature* caster = GetCaster()->ToCreature(); - caster->AI()->DoCastAOE(SPELL_SURGE_OF_POWER_PHASE_3_25); + GetCaster()->ToCreature()->AI()->DoCastAOE(SPELL_SURGE_OF_POWER_PHASE_3_25); } void Register() @@ -2374,8 +2334,6 @@ class spell_malygos_surge_of_power_warning_selector_25 : public SpellScriptLoade OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_malygos_surge_of_power_warning_selector_25_SpellScript::SendThreeTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); AfterHit += SpellHitFn(spell_malygos_surge_of_power_warning_selector_25_SpellScript::ExecuteMainSpell); } - - std::list<WorldObject*> _filteredSelectedTargets; }; SpellScript* GetSpellScript() const @@ -2401,25 +2359,25 @@ class spell_malygos_surge_of_power_25 : public SpellScriptLoader void FilterTargets(std::list<WorldObject*>& targets) { Creature* caster = GetCaster()->ToCreature(); - if (!targets.empty()) - targets.clear(); - for (int guidSlot = 14; guidSlot <= 16; guidSlot++) + for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end();) { - uint64 guidTypeChecker = caster->AI()->GetGUID(guidSlot); - if (IS_EMPTY_GUID(guidTypeChecker)) - continue; + bool found = false; + WorldObject* target = *itr; - if (IS_VEHICLE_GUID(guidTypeChecker)) - { - WorldObject* tempTarget = caster->GetMap()->GetCreature(guidTypeChecker); - targets.push_back(tempTarget); - } - else if (IS_PLAYER_GUID(guidTypeChecker)) + for (uint32 guidSlot = DATA_FIRST_SURGE_TARGET_GUID; guidSlot < DATA_FIRST_SURGE_TARGET_GUID + NUM_MAX_SURGE_TARGETS; ++guidSlot) { - WorldObject* tempTarget = ObjectAccessor::GetPlayer(*caster, guidTypeChecker); - targets.push_back(tempTarget); + if (target->GetGUID() == caster->AI()->GetGUID(guidSlot)) + { + found = true; + break; + } } + + if (!found) + targets.erase(itr++); + else + ++itr; } } @@ -2513,12 +2471,12 @@ class spell_alexstrasza_gift_beam_visual : public SpellScriptLoader if (InstanceScript* instance = GetCaster()->GetInstanceScript()) { _alexstraszaGift->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - if ((_heartMagic = target->GetMap()->GetGameObject(instance->GetData64(DATA_HEART_OF_MAGIC_GUID)))) + if (GameObject* heartMagic = target->GetMap()->GetGameObject(instance->GetData64(DATA_HEART_OF_MAGIC_GUID))) { - _heartMagic->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + heartMagic->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); // TO DO: This is hack, core doesn't have support for these flags, // remove line below if it ever gets supported otherwise object won't be accessible. - _heartMagic->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND); + heartMagic->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND); } } } @@ -2530,7 +2488,6 @@ class spell_alexstrasza_gift_beam_visual : public SpellScriptLoader } GameObject* _alexstraszaGift; - GameObject* _heartMagic; }; AuraScript* GetAuraScript() const |