diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 18 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 6 | ||||
-rw-r--r-- | src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp | 204 |
3 files changed, 178 insertions, 50 deletions
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index ba7c87ba10a..8b440b665ad 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -3212,24 +3212,6 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) switch (m_spellInfo->SpellFamilyName) { - case SPELLFAMILY_GENERIC: - { - switch (m_spellInfo->Id) - { - case 69055: // Saber Lash - case 70814: // Saber Lash - { - uint32 count = 0; - for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) - if (ihit->effectMask & (1 << effIndex)) - ++count; - - totalDamagePercentMod /= count; - break; - } - } - break; - } case SPELLFAMILY_WARRIOR: { // Devastate (player ones) diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index b258f01ccd5..dbd4e3904ea 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3397,9 +3397,9 @@ void SpellMgr::LoadDbcDataCorrections() case 70861: // Sindragosa's Lair Teleport spellInfo->EffectImplicitTargetA[0] = TARGET_DEST_DB; break; - case 69055: // Saber Lash (Lord Marrowgar) - case 70814: // Saber Lash (Lord Marrowgar) - spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_5_YARDS; // 5yd + case 69055: // Bone Slice (Lord Marrowgar) + case 70814: // Bone Slice (Lord Marrowgar) + spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_8_YARDS; // 5yd break; case 69075: // Bone Storm (Lord Marrowgar) case 70834: // Bone Storm (Lord Marrowgar) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp index 4763896cf72..5a669bc2a0b 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp @@ -20,8 +20,9 @@ #include "ScriptedCreature.h" #include "SpellAuras.h" #include "MapManager.h" -#include "icecrown_citadel.h" +#include "MoveSplineInit.h" #include "Player.h" +#include "icecrown_citadel.h" enum ScriptTexts { @@ -78,7 +79,46 @@ enum MovementPoints POINT_TARGET_COLDFLAME = 36672631, }; -#define DATA_COLDFLAME_GUID 0 +enum MiscInfo +{ + DATA_COLDFLAME_GUID = 0, + + // Manual marking for targets hit by Bone Slice as no aura exists for this purpose + // These units are the tanks in this encounter + // and should be immune to Bone Spike Graveyard + DATA_SPIKE_IMMUNE = 1, + //DATA_SPIKE_IMMUNE_1, = 2, // Reserved & used + //DATA_SPIKE_IMMUNE_2, = 3, // Reserved & used + + ACTION_CLEAR_SPIKE_IMMUNITIES = 1, + + MAX_BONE_SPIKE_IMMUNE = 3, +}; + +class BoneSpikeTargetSelector : public std::unary_function<Unit*, bool> +{ + public: + BoneSpikeTargetSelector(UnitAI* ai) : _ai(ai) { } + + bool operator()(Unit* unit) const + { + if (unit->GetTypeId() != TYPEID_PLAYER) + return false; + + if (unit->HasAura(SPELL_IMPALED)) + return false; + + // Check if it is one of the tanks soaking Bone Slice + for (uint32 i = 0; i < MAX_BONE_SPIKE_IMMUNE; ++i) + if (unit->GetGUID() == _ai->GetGUID(DATA_SPIKE_IMMUNE + i)) + return false; + + return true; + } + + private: + UnitAI* _ai; +}; class boss_lord_marrowgar : public CreatureScript { @@ -108,6 +148,7 @@ class boss_lord_marrowgar : public CreatureScript events.ScheduleEvent(EVENT_WARN_BONE_STORM, urand(45000, 50000)); events.ScheduleEvent(EVENT_ENRAGE, 600000); _boneSlice = false; + _boneSpikeImmune.clear(); } void EnterCombat(Unit* /*who*/) @@ -205,7 +246,7 @@ class boss_lord_marrowgar : public CreatureScript case EVENT_BONE_STORM_END: if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE) me->GetMotionMaster()->MovementExpired(); - DoStartMovement(me->getVictim()); + me->GetMotionMaster()->MoveChase(me->getVictim()); me->SetSpeed(MOVE_RUN, _baseSpeed, true); events.CancelEvent(EVENT_BONE_STORM_MOVE); events.ScheduleEvent(EVENT_ENABLE_BONE_SLICE, 10000); @@ -239,7 +280,7 @@ class boss_lord_marrowgar : public CreatureScript return; // lock movement - DoStartNoMovement(me->getVictim()); + me->GetMotionMaster()->MoveIdle(); } Position const* GetLastColdflamePosition() const @@ -247,23 +288,51 @@ class boss_lord_marrowgar : public CreatureScript return &_coldflameLastPos; } - uint64 GetGUID(int32 type/* = 0 */) const + uint64 GetGUID(int32 type /*= 0 */) const { - if (type == DATA_COLDFLAME_GUID) - return _coldflameTarget; + switch (type) + { + case DATA_COLDFLAME_GUID: + return _coldflameTarget; + case DATA_SPIKE_IMMUNE + 0: + case DATA_SPIKE_IMMUNE + 1: + case DATA_SPIKE_IMMUNE + 2: + { + int32 index = type - DATA_SPIKE_IMMUNE; + if (index < _boneSpikeImmune.size()) + return _boneSpikeImmune[index]; + + break; + } + } + return 0LL; } - void SetGUID(uint64 guid, int32 type/* = 0 */) + void SetGUID(uint64 guid, int32 type /*= 0 */) + { + switch (type) + { + case DATA_COLDFLAME_GUID: + _coldflameTarget = guid; + break; + case DATA_SPIKE_IMMUNE: + _boneSpikeImmune.push_back(guid); + break; + } + } + + void DoAction(int32 const action) { - if (type != DATA_COLDFLAME_GUID) + if (action != ACTION_CLEAR_SPIKE_IMMUNITIES) return; - _coldflameTarget = guid; + _boneSpikeImmune.clear(); } private: Position _coldflameLastPos; + std::vector<uint64> _boneSpikeImmune; uint64 _coldflameTarget; uint32 _boneStormDuration; float _baseSpeed; @@ -323,7 +392,7 @@ class npc_coldflame : public CreatureScript } me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), me->GetPositionZ(), me->GetOrientation()); - _events.ScheduleEvent(EVENT_COLDFLAME_TRIGGER, 450); + _events.ScheduleEvent(EVENT_COLDFLAME_TRIGGER, 500); } void UpdateAI(uint32 const diff) @@ -333,10 +402,10 @@ class npc_coldflame : public CreatureScript if (_events.ExecuteEvent() == EVENT_COLDFLAME_TRIGGER) { Position newPos; - me->GetNearPosition(newPos, 5.5f, 0.0f); + me->GetNearPosition(newPos, 5.0f, 0.0f); me->NearTeleportTo(newPos.GetPositionX(), newPos.GetPositionY(), me->GetPositionZ(), me->GetOrientation()); DoCast(SPELL_COLDFLAME_SUMMON); - _events.ScheduleEvent(EVENT_COLDFLAME_TRIGGER, 450); + _events.ScheduleEvent(EVENT_COLDFLAME_TRIGGER, 500); } } @@ -385,6 +454,24 @@ class npc_bone_spike : public CreatureScript _hasTrappedUnit = true; } + void PassengerBoarded(Unit* passenger, int8 /*seat*/, bool apply) + { + if (!apply) + return; + + /// @HACK - Change passenger offset to the one taken directly from sniffs + /// Remove this when proper calculations are implemented. + /// This fixes healing spiked people + Movement::MoveSplineInit init(passenger); + init.DisableTransportPathTransformations(); + init.MoveTo(-0.02206125f, -0.02132235f, 5.514783f, false); + init.Launch(); + + /// @WORKAROUND - Clear ON VEHICLE state to allow healing (Invalid target errors) + /// Current rule for applying this state is questionable (seatFlags & VEHICLE_SEAT_FLAG_ALLOW_TURNING ???) + passenger->ClearUnitState(UNIT_STATE_ONVEHICLE); + } + void UpdateAI(uint32 const diff) { if (!_hasTrappedUnit) @@ -487,16 +574,24 @@ class spell_marrowgar_coldflame_damage : public SpellScriptLoader { PrepareAuraScript(spell_marrowgar_coldflame_damage_AuraScript); - void OnPeriodic(AuraEffect const* /*aurEff*/) + bool CanBeAppliedOn(Unit* target) { - if (DynamicObject* owner = GetDynobjOwner()) - if (GetTarget()->GetExactDist2d(owner) >= owner->GetRadius() || GetTarget()->HasAura(SPELL_IMPALED)) - PreventDefaultAction(); + if (target->HasAura(SPELL_IMPALED)) + return false; + + if (target->GetExactDist2d(GetOwner()) > GetSpellInfo()->Effects[EFFECT_0].CalcRadius()) + return false; + + if (Aura* aur = target->GetAura(GetId())) + if (aur->GetOwner() != GetOwner()) + return false; + + return true; } void Register() { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_marrowgar_coldflame_damage_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); + DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_marrowgar_coldflame_damage_AuraScript::CanBeAppliedOn); } }; @@ -531,7 +626,7 @@ class spell_marrowgar_bone_spike_graveyard : public SpellScriptLoader SpellCastResult CheckCast() { - return GetCaster()->GetAI()->SelectTarget(SELECT_TARGET_TOPAGGRO, 1, 0.0f, true, -SPELL_IMPALED) ? SPELL_CAST_OK : SPELL_FAILED_NO_VALID_TARGETS; + return GetCaster()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0, BoneSpikeTargetSelector(GetCaster()->GetAI())) ? SPELL_CAST_OK : SPELL_FAILED_NO_VALID_TARGETS; } void HandleSpikes(SpellEffIndex effIndex) @@ -539,22 +634,22 @@ class spell_marrowgar_bone_spike_graveyard : public SpellScriptLoader PreventHitDefaultEffect(effIndex); if (Creature* marrowgar = GetCaster()->ToCreature()) { - bool didHit = false; CreatureAI* marrowgarAI = marrowgar->AI(); uint8 boneSpikeCount = uint8(GetCaster()->GetMap()->GetSpawnMode() & 1 ? 3 : 1); - for (uint8 i = 0; i < boneSpikeCount; ++i) - { - // select any unit but not the tank - Unit* target = marrowgarAI->SelectTarget(SELECT_TARGET_RANDOM, 1, 150.0f, true, -SPELL_IMPALED); - if (!target) - break; - didHit = true; + std::list<Unit*> targets; + marrowgarAI->SelectTargetList(targets, BoneSpikeTargetSelector(marrowgarAI), boneSpikeCount, SELECT_TARGET_RANDOM); + if (targets.empty()) + return; + + uint32 i = 0; + for (std::list<Unit*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr, ++i) + { + Unit* target = *itr; target->CastCustomSpell(BoneSpikeSummonId[i], SPELLVALUE_BASE_POINT0, 0, target, true); } - if (didHit) - marrowgarAI->Talk(SAY_BONESPIKE); + marrowgarAI->Talk(SAY_BONESPIKE); } } @@ -597,6 +692,56 @@ class spell_marrowgar_bone_storm : public SpellScriptLoader } }; +class spell_marrowgar_bone_slice : public SpellScriptLoader +{ + public: + spell_marrowgar_bone_slice() : SpellScriptLoader("spell_marrowgar_bone_slice") { } + + class spell_marrowgar_bone_slice_SpellScript : public SpellScript + { + PrepareSpellScript(spell_marrowgar_bone_slice_SpellScript); + + bool Load() + { + _targetCount = 0; + return true; + } + + void ClearSpikeImmunities() + { + GetCaster()->GetAI()->DoAction(ACTION_CLEAR_SPIKE_IMMUNITIES); + } + + void CountTarget(SpellEffIndex /*effIndex*/) + { + ++_targetCount; + GetCaster()->GetAI()->SetGUID(GetHitUnit()->GetGUID(), DATA_SPIKE_IMMUNE); + } + + void SplitDamage() + { + if (!_targetCount) + return; // why would there be an unit not hit by effect hook and hit by this? + + SetHitDamage(GetHitDamage() / _targetCount); + } + + void Register() + { + BeforeCast += SpellCastFn(spell_marrowgar_bone_slice_SpellScript::ClearSpikeImmunities); + OnEffectLaunchTarget += SpellEffectFn(spell_marrowgar_bone_slice_SpellScript::CountTarget, EFFECT_0, SPELL_EFFECT_WEAPON_PERCENT_DAMAGE); + OnHit += SpellHitFn(spell_marrowgar_bone_slice_SpellScript::SplitDamage); + } + + uint32 _targetCount; + }; + + SpellScript* GetSpellScript() const + { + return new spell_marrowgar_bone_slice_SpellScript(); + } +}; + void AddSC_boss_lord_marrowgar() { new boss_lord_marrowgar(); @@ -607,4 +752,5 @@ void AddSC_boss_lord_marrowgar() new spell_marrowgar_coldflame_damage(); new spell_marrowgar_bone_spike_graveyard(); new spell_marrowgar_bone_storm(); + new spell_marrowgar_bone_slice(); } |