aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp13
-rwxr-xr-xsrc/server/game/Spells/SpellMgr.cpp13
-rwxr-xr-xsrc/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp205
3 files changed, 139 insertions, 92 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 0e7ffcecd0b..d5d83b3a7df 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -8517,6 +8517,11 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig
target = pVictim;
break;
}
+ // Professor Putricide - Ooze Spell Tank Protection
+ case 71770:
+ if (pVictim)
+ pVictim->CastSpell(pVictim, trigger_spell_id, true); // EffectImplicitTarget is self
+ return true;
default:
break;
}
@@ -8544,7 +8549,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig
// Custom basepoints/target for exist spell
// dummy basepoints or other customs
- switch(trigger_spell_id)
+ switch (trigger_spell_id)
{
// Auras which should proc on area aura source (caster in this case):
// Turn the Tables
@@ -8723,10 +8728,6 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig
return false;
break;
}
- // Deathbringer Saurfang - Blood Link
- case 72202:
- target = FindNearestCreature(37813, 75.0f); // NPC_DEATHBRINGER_SAURFANG = 37813
- break;
// Shadow's Fate (Shadowmourne questline)
case 71169:
{
@@ -8766,7 +8767,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig
// try detect target manually if not set
if (target == NULL)
- target = !(procFlags & (PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS | PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS)) && IsPositiveSpell(trigger_spell_id) ? this : pVictim;
+ target = !(procFlags & (PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS | PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS)) && IsPositiveSpell(trigger_spell_id) ? this : pVictim;
// default case
if ((!target && !sSpellMgr->IsSrcTargetSpell(triggerEntry)) || (target && target != this && !target->isAlive()))
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 3308332ce04..b6edca815ea 100755
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -4033,19 +4033,6 @@ void SpellMgr::LoadSpellCustomAttr()
spellInfo->Effect[1] = 0;
count++;
break;
- case 70447: // Volatile Ooze Adhesive (Professor Putricide)
- case 72836: // Volatile Ooze Adhesive (Professor Putricide)
- case 72837: // Volatile Ooze Adhesive (Professor Putricide)
- case 72838: // Volatile Ooze Adhesive (Professor Putricide)
- case 70672: // Gaseous Bloat (Professor Putricide)
- case 72455: // Gaseous Bloat (Professor Putricide)
- case 72832: // Gaseous Bloat (Professor Putricide)
- case 72833: // Gaseous Bloat (Professor Putricide)
- spellInfo->EffectImplicitTargetB[0] = TARGET_UNIT_TARGET_ENEMY;
- spellInfo->EffectImplicitTargetB[1] = TARGET_UNIT_TARGET_ENEMY;
- spellInfo->EffectImplicitTargetB[2] = TARGET_UNIT_TARGET_ENEMY;
- count++;
- break;
case 70911: // Unbound Plague (Professor Putricide)
case 72854: // Unbound Plague (Professor Putricide)
case 72855: // Unbound Plague (Professor Putricide)
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
index 4b60b306048..ef6e78f13d2 100755
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
@@ -163,20 +163,6 @@ enum PutricideData
#define EXPERIMENT_STATE_OOZE false
#define EXPERIMENT_STATE_GAS true
-class StartMovementEvent : public BasicEvent
-{
- public:
- StartMovementEvent(Creature& owner) : BasicEvent(), m_owner(owner) { }
- bool Execute(uint64 /*eventTime*/, uint32 /*diff*/)
- {
- m_owner.GetMotionMaster()->MoveChase(m_owner.getVictim());
- return true;
- }
-
- private:
- Creature& m_owner;
-};
-
class boss_professor_putricide : public CreatureScript
{
public:
@@ -198,7 +184,7 @@ class boss_professor_putricide : public CreatureScript
events.Reset();
summons.DespawnAll();
- _SetPhase(PHASE_COMBAT_1);
+ SetPhase(PHASE_COMBAT_1);
experimentState = EXPERIMENT_STATE_OOZE;
me->SetReactState(REACT_DEFENSIVE);
me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
@@ -229,7 +215,7 @@ class boss_professor_putricide : public CreatureScript
if (IsHeroic())
events.ScheduleEvent(EVENT_UNBOUND_PLAGUE, 20000);
- _SetPhase(PHASE_COMBAT_1);
+ SetPhase(PHASE_COMBAT_1);
Talk(SAY_AGGRO);
DoCast(me, SPELL_OOZE_TANK_PROTECTION, true);
DoZoneInCombat(me);
@@ -268,30 +254,17 @@ class boss_professor_putricide : public CreatureScript
break;
case NPC_GAS_CLOUD:
// no possible aura seen in sniff adding the aurastate
- summon->SetFlag(UNIT_FIELD_AURASTATE, 1 << (AURA_STATE_UNKNOWN22-1));
+ summon->SetFlag(UNIT_FIELD_AURASTATE, 1 << (AURA_STATE_UNKNOWN22 - 1));
summon->CastSpell(summon, SPELL_GASEOUS_BLOAT_PROC, true);
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_GASEOUS_BLOAT_PROTECTION))
- {
- summon->AI()->AttackStart(target);
- summon->CastCustomSpell(SPELL_GASEOUS_BLOAT, SPELLVALUE_MAX_TARGETS, 1, target, false);
- summon->ClearUnitState(UNIT_STAT_CASTING);
- summon->GetMotionMaster()->MoveIdle();
- summon->m_Events.AddEvent(new StartMovementEvent(*summon), summon->m_Events.CalculateTime(3500));
- }
+ summon->CastSpell(summon, SPELL_GASEOUS_BLOAT, false);
+ summon->SetReactState(REACT_PASSIVE);
return;
case NPC_VOLATILE_OOZE:
// no possible aura seen in sniff adding the aurastate
- summon->SetFlag(UNIT_FIELD_AURASTATE, 1 << (AURA_STATE_UNKNOWN19-1));
+ summon->SetFlag(UNIT_FIELD_AURASTATE, 1 << (AURA_STATE_UNKNOWN19 - 1));
summon->CastSpell(summon, SPELL_OOZE_ERUPTION_SEARCH_PERIODIC, true);
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_VOLATILE_OOZE_PROTECTION))
- {
- summon->AI()->AttackStart(target);
- summon->CastCustomSpell(SPELL_VOLATILE_OOZE_ADHESIVE, SPELLVALUE_MAX_TARGETS, 1, target, false);
- summon->ClearUnitState(UNIT_STAT_CASTING);
- summon->GetMotionMaster()->MoveIdle();
- summon->m_Events.AddEvent(new StartMovementEvent(*summon), summon->m_Events.CalculateTime(3500));
- me->SetReactState(REACT_PASSIVE);
- }
+ summon->CastSpell(summon, SPELL_VOLATILE_OOZE_ADHESIVE, false);
+ summon->SetReactState(REACT_PASSIVE);
return;
case NPC_CHOKING_GAS_BOMB:
summon->CastSpell(summon, SPELL_CHOKING_GAS_BOMB_PERIODIC, true);
@@ -303,6 +276,7 @@ class boss_professor_putricide : public CreatureScript
default:
break;
}
+
if (me->isInCombat())
DoZoneInCombat(summon);
}
@@ -381,12 +355,12 @@ class boss_professor_putricide : public CreatureScript
}
}
- void DoAction(const int32 action)
+ void DoAction(int32 const action)
{
switch (action)
{
case ACTION_FESTERGUT_COMBAT:
- _SetPhase(PHASE_FESTERGUT);
+ SetPhase(PHASE_FESTERGUT);
me->SetSpeed(MOVE_RUN, baseSpeed*2.0f, true);
me->GetMotionMaster()->MovePoint(POINT_FESTERGUT, festergutWatchPos);
me->SetReactState(REACT_PASSIVE);
@@ -403,7 +377,7 @@ class boss_professor_putricide : public CreatureScript
break;
case ACTION_ROTFACE_COMBAT:
{
- _SetPhase(PHASE_ROTFACE);
+ SetPhase(PHASE_ROTFACE);
me->SetSpeed(MOVE_RUN, baseSpeed*2.0f, true);
me->GetMotionMaster()->MovePoint(POINT_ROTFACE, rotfaceWatchPos);
me->SetReactState(REACT_PASSIVE);
@@ -489,12 +463,12 @@ class boss_professor_putricide : public CreatureScript
switch (phase)
{
case PHASE_COMBAT_1:
- _SetPhase(PHASE_COMBAT_2);
+ SetPhase(PHASE_COMBAT_2);
events.ScheduleEvent(EVENT_MALLEABLE_GOO, urand(21000, 26000));
events.ScheduleEvent(EVENT_CHOKING_GAS_BOMB, urand(35000, 40000));
break;
case PHASE_COMBAT_2:
- _SetPhase(PHASE_COMBAT_3);
+ SetPhase(PHASE_COMBAT_3);
events.ScheduleEvent(EVENT_MUTATED_PLAGUE, 25000);
events.CancelEvent(EVENT_UNSTABLE_EXPERIMENT);
summons.DespawnEntry(NPC_MUTATED_ABOMINATION_10);
@@ -532,7 +506,7 @@ class boss_professor_putricide : public CreatureScript
return 0;
}
- void UpdateAI(const uint32 diff)
+ void UpdateAI(uint32 const diff)
{
if ((!UpdateVictim() && !(events.GetPhaseMask() & PHASE_MASK_NOT_SELF)) || !CheckInRoom())
return;
@@ -667,7 +641,7 @@ class boss_professor_putricide : public CreatureScript
}
private:
- void _SetPhase(Phases newPhase)
+ void SetPhase(Phases newPhase)
{
phase = newPhase;
events.SetPhase(newPhase);
@@ -675,7 +649,7 @@ class boss_professor_putricide : public CreatureScript
uint64 oozeFloodDummy[4];
Phases phase; // external of EventMap because event phase gets reset on evade
- const float baseSpeed;
+ float const baseSpeed;
uint8 oozeFloodStage;
bool experimentState;
};
@@ -700,22 +674,13 @@ class npc_volatile_ooze : public CreatureScript
void SpellHitTarget(Unit* /*target*/, SpellEntry const* spell)
{
- SpellEntry const* explode = sSpellStore.LookupEntry(SPELL_OOZE_ERUPTION);
- explode = sSpellMgr->GetSpellForDifficultyFromSpell(explode, me);
- if (explode->Id == spell->Id)
- {
- newTargetSelectTimer = 5000;
- DoStartNoMovement(me);
- }
+ if (!newTargetSelectTimer && sSpellMgr->GetSpellDifficultyId(spell->Id) == sSpellMgr->GetSpellDifficultyId(SPELL_OOZE_ERUPTION))
+ newTargetSelectTimer = 1000;
}
- void UpdateAI(const uint32 diff)
+ void UpdateAI(uint32 const diff)
{
- // simplified update, we do not want to select new target
- if (!me->isInCombat())
- return;
-
- if (!me->getVictim())
+ if (!UpdateVictim())
return;
if (!newTargetSelectTimer)
@@ -724,13 +689,7 @@ class npc_volatile_ooze : public CreatureScript
if (newTargetSelectTimer <= diff)
{
newTargetSelectTimer = 0;
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_VOLATILE_OOZE_PROTECTION))
- {
- AttackStart(target);
- me->CastCustomSpell(SPELL_VOLATILE_OOZE_ADHESIVE, SPELLVALUE_MAX_TARGETS, 1, target, false);
- }
- else
- me->DespawnOrUnsummon();
+ me->CastSpell(me, SPELL_VOLATILE_OOZE_ADHESIVE, false);
}
else
newTargetSelectTimer -= diff;
@@ -774,7 +733,11 @@ class spell_putricide_gaseous_bloat : public SpellScriptLoader
void HandleExtraEffect(AuraEffect const* /*aurEff*/)
{
- GetTarget()->RemoveAuraFromStack(GetSpellProto()->Id, GetCasterGUID());
+ Unit* target = GetTarget();
+ Unit* caster = GetCaster();
+ target->RemoveAuraFromStack(GetSpellProto()->Id, GetCasterGUID());
+ if (!target->HasAura(GetId()) && caster && caster->GetTypeId() == TYPEID_UNIT)
+ caster->ToCreature()->DespawnOrUnsummon();
}
void Register()
@@ -794,6 +757,94 @@ class spell_putricide_gaseous_bloat : public SpellScriptLoader
}
};
+class BeamProtectionPred
+{
+ public:
+ explicit BeamProtectionPred(uint32 excludeAura) : _excludeAura(excludeAura) { }
+
+ bool operator()(Unit* unit)
+ {
+ return unit->HasAura(_excludeAura);
+ }
+
+ private:
+ uint32 _excludeAura;
+};
+
+class spell_putricide_ooze_channel : public SpellScriptLoader
+{
+ public:
+ spell_putricide_ooze_channel() : SpellScriptLoader("spell_putricide_ooze_channel") { }
+
+ class spell_putricide_ooze_channel_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_putricide_ooze_channel_SpellScript);
+
+ bool Validate(SpellEntry const* spell)
+ {
+ if (!spell->excludeTargetAuraSpell)
+ return false;
+ if (!sSpellStore.LookupEntry(spell->excludeTargetAuraSpell))
+ return false;
+ return true;
+ }
+
+ // set up initial variables and check if caster is creature
+ // this will let use safely use ToCreature() casts in entire script
+ bool Load()
+ {
+ _target = NULL;
+ return GetCaster()->GetTypeId() == TYPEID_UNIT;
+ }
+
+ void SelectTarget(std::list<Unit*>& targetList)
+ {
+ targetList.remove_if(BeamProtectionPred(GetSpellInfo()->excludeTargetAuraSpell));
+ if (targetList.empty())
+ {
+ FinishCast(SPELL_FAILED_NO_VALID_TARGETS);
+ GetCaster()->ToCreature()->DespawnOrUnsummon(1); // despawn next update
+ return;
+ }
+
+ std::list<Unit*>::iterator itr = targetList.begin();
+ std::advance(itr, urand(0, targetList.size() - 1));
+ Unit* target = *itr;
+ targetList.clear();
+ targetList.push_back(target);
+ _target = target;
+ }
+
+ void SetTarget(std::list<Unit*>& targetList)
+ {
+ targetList.clear();
+ if (_target)
+ targetList.push_back(_target);
+ }
+
+ void StartAttack()
+ {
+ GetCaster()->ClearUnitState(UNIT_STAT_CASTING);
+ GetCaster()->ToCreature()->AI()->AttackStart(GetHitUnit());
+ }
+
+ void Register()
+ {
+ OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_ooze_channel_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_AREA_ENEMY_SRC);
+ OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_ooze_channel_SpellScript::SetTarget, EFFECT_1, TARGET_UNIT_AREA_ENEMY_SRC);
+ OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_ooze_channel_SpellScript::SetTarget, EFFECT_2, TARGET_UNIT_AREA_ENEMY_SRC);
+ AfterHit += SpellHitFn(spell_putricide_ooze_channel_SpellScript::StartAttack);
+ }
+
+ Unit* _target;
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_putricide_ooze_channel_SpellScript();
+ }
+};
+
class spell_putricide_expunged_gas : public SpellScriptLoader
{
public:
@@ -803,11 +854,13 @@ class spell_putricide_expunged_gas : public SpellScriptLoader
{
PrepareSpellScript(spell_putricide_expunged_gas_SpellScript);
- void CalcDamage(SpellEffIndex /*effIndex*/)
+ bool Load()
{
- if (GetCaster()->GetTypeId() != TYPEID_UNIT)
- return;
+ return GetCaster()->GetTypeId() == TYPEID_UNIT;
+ }
+ void CalcDamage(SpellEffIndex /*effIndex*/)
+ {
InstanceScript* instance = GetCaster()->GetInstanceScript();
if (!instance)
return;
@@ -817,23 +870,28 @@ class spell_putricide_expunged_gas : public SpellScriptLoader
return;
int32 dmg = 0;
- ScriptedAI* professorAI = CAST_AI(ScriptedAI, professor->AI());
- if (Aura* gasBloat = GetTargetUnit()->GetAura(professorAI->SPELL_GASEOUS_BLOAT_HELPER))
+ SpellEntry const* bloat = sSpellStore.LookupEntry(SPELL_GASEOUS_BLOAT);
+ bloat = sSpellMgr->GetSpellForDifficultyFromSpell(bloat, GetCaster());
+ if (Aura* gasBloat = GetTargetUnit()->GetAura(bloat->Id))
{
uint32 stack = gasBloat->GetStackAmount();
- const int32 mod = professorAI->Is25ManRaid() ? 1500 : 1250;
+ int32 const mod = (GetCaster()->GetMap()->GetSpawnMode() & 1) ? 1500 : 1250;
for (uint8 i = 1; i < stack; ++i)
dmg += mod * stack;
}
- else
- GetCaster()->ToCreature()->DespawnOrUnsummon();
SetHitDamage(dmg);
}
+ void DespawnAfterCast()
+ {
+ GetCaster()->ToCreature()->DespawnOrUnsummon(100);
+ }
+
void Register()
{
OnEffect += SpellEffectFn(spell_putricide_expunged_gas_SpellScript::CalcDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
+ AfterHit += SpellHitFn(spell_putricide_expunged_gas_SpellScript::DespawnAfterCast);
}
};
@@ -974,7 +1032,7 @@ class spell_putricide_ooze_eruption_searcher : public SpellScriptLoader
if (GetHitUnit()->HasAura(adhesive->Id))
{
GetCaster()->CastSpell(GetHitUnit(), SPELL_OOZE_ERUPTION, true);
- GetHitUnit()->RemoveAurasDueToSpell(adhesive->Id, GetCaster()->GetGUID());
+ GetHitUnit()->RemoveAurasDueToSpell(adhesive->Id, GetCaster()->GetGUID(), 0, AURA_REMOVE_BY_ENEMY_SPELL);
}
}
@@ -1448,6 +1506,7 @@ void AddSC_boss_professor_putricide()
new boss_professor_putricide();
new npc_volatile_ooze();
new spell_putricide_gaseous_bloat();
+ new spell_putricide_ooze_channel();
new spell_putricide_expunged_gas();
new spell_putricide_slime_puddle();
new spell_putricide_unstable_experiment();