Merge commit '6390e6a4cc2d657e7fa49e80c5be32007df56ee1' into 4.3.4

Conflicts:
	sql/updates/world/2014_12_30_00_world.sql
	sql/updates/world/2014_12_30_01_world.sql
	src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp
This commit is contained in:
Carbenium
2015-07-21 20:45:16 +02:00
6 changed files with 284 additions and 172 deletions

View File

@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2015 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
@@ -20,8 +19,8 @@
#include "ScriptedCreature.h"
#include "SpellScript.h"
#include "SpellAuraEffects.h"
#include "nexus.h"
#include "Player.h"
#include "nexus.h"
enum Spells
{
@@ -31,15 +30,21 @@ enum Spells
SPELL_CRYSTAL_CHAINS = 50997,
SPELL_ENRAGE = 8599,
SPELL_CRYSTALFIRE_BREATH = 48096,
H_SPELL_CRYSTALFIRE_BREATH = 57091,
SPELL_CRYSTALIZE = 48179,
SPELL_INTENSE_COLD = 48094,
SPELL_INTENSE_COLD_TRIGGERED = 48095
};
enum Events
{
EVENT_CRYSTAL_FIRE_BREATH = 1,
EVENT_CRYSTAL_CHAINS_CRYSTALIZE,
EVENT_TAIL_SWEEP
};
enum Yells
{
//Yell
// Yell
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_ENRAGE = 2,
@@ -51,163 +56,166 @@ enum Yells
enum Misc
{
DATA_INTENSE_COLD = 1,
DATA_CONTAINMENT_SPHERES = 3,
DATA_CONTAINMENT_SPHERES = 3
};
class boss_keristrasza : public CreatureScript
{
public:
boss_keristrasza() : CreatureScript("boss_keristrasza") { }
public:
boss_keristrasza() : CreatureScript("boss_keristrasza") { }
CreatureAI* GetAI(Creature* creature) const override
{
return GetInstanceAI<boss_keristraszaAI>(creature);
}
struct boss_keristraszaAI : public ScriptedAI
{
boss_keristraszaAI(Creature* creature) : ScriptedAI(creature)
struct boss_keristraszaAI : public BossAI
{
Initialize();
instance = creature->GetInstanceScript();
}
void Initialize()
{
uiCrystalfireBreathTimer = 14 * IN_MILLISECONDS;
uiCrystalChainsCrystalizeTimer = DUNGEON_MODE(30 * IN_MILLISECONDS, 11 * IN_MILLISECONDS);
uiTailSweepTimer = 5 * IN_MILLISECONDS;
bEnrage = false;
intenseCold = true;
}
InstanceScript* instance;
GuidList intenseColdList;
ObjectGuid auiContainmentSphereGUIDs[DATA_CONTAINMENT_SPHERES];
uint32 uiCrystalfireBreathTimer;
uint32 uiCrystalChainsCrystalizeTimer;
uint32 uiTailSweepTimer;
bool intenseCold;
bool bEnrage;
void Reset() override
{
Initialize();
intenseColdList.clear();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
RemovePrison(CheckContainmentSpheres());
instance->SetBossState(DATA_KERISTRASZA, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
DoCastAOE(SPELL_INTENSE_COLD);
instance->SetBossState(DATA_KERISTRASZA, IN_PROGRESS);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
instance->SetBossState(DATA_KERISTRASZA, DONE);
}
void KilledUnit(Unit* who) override
{
if (who->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
bool CheckContainmentSpheres(bool remove_prison = false)
{
auiContainmentSphereGUIDs[0] = instance->GetGuidData(ANOMALUS_CONTAINMET_SPHERE);
auiContainmentSphereGUIDs[1] = instance->GetGuidData(ORMOROKS_CONTAINMET_SPHERE);
auiContainmentSphereGUIDs[2] = instance->GetGuidData(TELESTRAS_CONTAINMET_SPHERE);
GameObject* ContainmentSpheres[DATA_CONTAINMENT_SPHERES];
for (uint8 i = 0; i < DATA_CONTAINMENT_SPHERES; ++i)
boss_keristraszaAI(Creature* creature) : BossAI(creature, DATA_KERISTRASZA)
{
ContainmentSpheres[i] = instance->instance->GetGameObject(auiContainmentSphereGUIDs[i]);
if (!ContainmentSpheres[i])
return false;
if (ContainmentSpheres[i]->GetGoState() != GO_STATE_ACTIVE)
return false;
}
if (remove_prison)
RemovePrison(true);
return true;
}
void RemovePrison(bool remove)
{
if (remove)
{
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
if (me->HasAura(SPELL_FROZEN_PRISON))
me->RemoveAurasDueToSpell(SPELL_FROZEN_PRISON);
}
else
{
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
DoCast(me, SPELL_FROZEN_PRISON, false);
}
}
void SetGUID(ObjectGuid guid, int32 id/* = 0 */) override
{
if (id == DATA_INTENSE_COLD)
intenseColdList.push_back(guid);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (!bEnrage && HealthBelowPct(25))
{
Talk(SAY_ENRAGE);
Talk(SAY_FRENZY);
DoCast(me, SPELL_ENRAGE);
bEnrage = true;
Initialize();
}
if (uiCrystalfireBreathTimer <= diff)
void Initialize()
{
DoCastVictim(SPELL_CRYSTALFIRE_BREATH);
uiCrystalfireBreathTimer = 14*IN_MILLISECONDS;
} else uiCrystalfireBreathTimer -= diff;
_enrage = false;
_intenseCold = true;
}
if (uiTailSweepTimer <= diff)
void Reset() override
{
DoCast(me, SPELL_TAIL_SWEEP);
uiTailSweepTimer = 5*IN_MILLISECONDS;
} else uiTailSweepTimer -= diff;
Initialize();
_intenseColdList.clear();
if (uiCrystalChainsCrystalizeTimer <= diff)
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
RemovePrison(CheckContainmentSpheres());
_Reset();
}
void EnterCombat(Unit* /*who*/) override
{
Talk(SAY_CRYSTAL_NOVA);
if (IsHeroic())
DoCast(me, SPELL_CRYSTALIZE);
else if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(target, SPELL_CRYSTAL_CHAINS);
uiCrystalChainsCrystalizeTimer = DUNGEON_MODE(30*IN_MILLISECONDS, 11*IN_MILLISECONDS);
} else uiCrystalChainsCrystalizeTimer -= diff;
Talk(SAY_AGGRO);
DoCastAOE(SPELL_INTENSE_COLD);
_EnterCombat();
DoMeleeAttackIfReady();
events.ScheduleEvent(EVENT_CRYSTAL_FIRE_BREATH, 14000);
events.ScheduleEvent(EVENT_CRYSTAL_CHAINS_CRYSTALIZE, DUNGEON_MODE(30000, 11000));
events.ScheduleEvent(EVENT_TAIL_SWEEP, 5000);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
_JustDied();
}
void KilledUnit(Unit* who) override
{
if (who->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
bool CheckContainmentSpheres(bool remove_prison = false)
{
ContainmentSphereGUIDs[0] = instance->GetGuidData(ANOMALUS_CONTAINMET_SPHERE);
ContainmentSphereGUIDs[1] = instance->GetGuidData(ORMOROKS_CONTAINMET_SPHERE);
ContainmentSphereGUIDs[2] = instance->GetGuidData(TELESTRAS_CONTAINMET_SPHERE);
GameObject* ContainmentSpheres[DATA_CONTAINMENT_SPHERES];
for (uint8 i = 0; i < DATA_CONTAINMENT_SPHERES; ++i)
{
ContainmentSpheres[i] = ObjectAccessor::GetGameObject(*me, ContainmentSphereGUIDs[i]);
if (!ContainmentSpheres[i])
return false;
if (ContainmentSpheres[i]->GetGoState() != GO_STATE_ACTIVE)
return false;
}
if (remove_prison)
RemovePrison(true);
return true;
}
void RemovePrison(bool remove)
{
if (remove)
{
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
if (me->HasAura(SPELL_FROZEN_PRISON))
me->RemoveAurasDueToSpell(SPELL_FROZEN_PRISON);
}
else
{
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
DoCast(me, SPELL_FROZEN_PRISON, false);
}
}
void SetGUID(ObjectGuid guid, int32 id/* = 0 */) override
{
if (id == DATA_INTENSE_COLD)
_intenseColdList.push_back(guid);
}
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
if (!_enrage && me->HealthBelowPctDamaged(25, damage))
{
Talk(SAY_ENRAGE);
Talk(SAY_FRENZY);
DoCast(me, SPELL_ENRAGE);
_enrage = true;
}
}
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_CRYSTAL_FIRE_BREATH:
DoCastVictim(SPELL_CRYSTALFIRE_BREATH);
events.ScheduleEvent(EVENT_CRYSTAL_FIRE_BREATH, 14000);
break;
case EVENT_CRYSTAL_CHAINS_CRYSTALIZE:
DoCast(me, SPELL_TAIL_SWEEP);
events.ScheduleEvent(EVENT_CRYSTAL_CHAINS_CRYSTALIZE, 5000);
break;
case EVENT_TAIL_SWEEP:
Talk(SAY_CRYSTAL_NOVA);
if (IsHeroic())
DoCast(me, SPELL_CRYSTALIZE);
else if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
DoCast(target, SPELL_CRYSTAL_CHAINS);
events.ScheduleEvent(EVENT_TAIL_SWEEP, DUNGEON_MODE(30000, 11000));
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
bool _intenseCold;
bool _enrage;
ObjectGuid ContainmentSphereGUIDs[DATA_CONTAINMENT_SPHERES];
public:
GuidList _intenseColdList;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetInstanceAI<boss_keristraszaAI>(creature);
}
};
};
class containment_sphere : public GameObjectScript
@@ -277,9 +285,9 @@ class achievement_intense_cold : public AchievementCriteriaScript
if (!target)
return false;
GuidList intenseColdList = ENSURE_AI(boss_keristrasza::boss_keristraszaAI, target->ToCreature()->AI())->intenseColdList;
if (!intenseColdList.empty())
for (GuidList::iterator itr = intenseColdList.begin(); itr != intenseColdList.end(); ++itr)
GuidList _intenseColdList = ENSURE_AI(boss_keristrasza::boss_keristraszaAI, target->ToCreature()->AI())->_intenseColdList;
if (!_intenseColdList.empty())
for (GuidList::iterator itr = _intenseColdList.begin(); itr != _intenseColdList.end(); ++itr)
if (player->GetGUID() == *itr)
return false;

View File

@@ -548,6 +548,11 @@ class boss_flame_leviathan : public CreatureScript
if (me->isAttackReady())
{
Unit* target = ObjectAccessor::GetUnit(*me, _pursueTarget);
// Pursue was unable to acquire a valid target, so get the current victim as target.
if (!target && me->GetVictim())
target = me->GetVictim();
if (me->IsWithinCombatRange(target, 30.0f))
{
DoCast(target, SPELL_BATTERING_RAM);
@@ -1648,7 +1653,7 @@ class FlameLeviathanPursuedTargetSelector
bool operator()(WorldObject* target) const
{
//! No players, only vehicles (@todo check if blizzlike)
//! No players, only vehicles. Pursue is never cast on players.
Creature* creatureTarget = target->ToCreature();
if (!creatureTarget)
return true;
@@ -1698,12 +1703,7 @@ class spell_pursue : public SpellScriptLoader
void FilterTargets(std::list<WorldObject*>& targets)
{
targets.remove_if(FlameLeviathanPursuedTargetSelector(GetCaster()));
if (targets.empty())
{
if (Creature* caster = GetCaster()->ToCreature())
caster->AI()->EnterEvadeMode();
}
else
if (!targets.empty())
{
//! In the end, only one target should be selected
_target = Trinity::Containers::SelectRandomContainerElement(targets);

View File

@@ -140,8 +140,8 @@ enum AncestralWolf
{
EMOTE_WOLF_LIFT_HEAD = 0,
EMOTE_WOLF_HOWL = 1,
SAY_WOLF_WELCOME = 2,
SPELL_ANCESTRAL_WOLF_BUFF = 29981,
SAY_WOLF_WELCOME = 0,
SPELL_ANCESTRAL_WOLF_BUFF = 29938,
NPC_RYGA = 17123
};
@@ -166,11 +166,16 @@ public:
void Reset() override
{
ryga = NULL;
}
// Override Evade Mode event, recast buff that was removed by standard handler
void EnterEvadeMode() override
{
npc_escortAI::EnterEvadeMode();
DoCast(me, SPELL_ANCESTRAL_WOLF_BUFF, true);
}
void MoveInLineOfSight(Unit* who) override
{
if (!ryga && who->GetEntry() == NPC_RYGA && me->IsWithinDistInMap(who, 15.0f))
if (Creature* temp = who->ToCreature())
@@ -188,10 +193,48 @@ public:
break;
case 2:
Talk(EMOTE_WOLF_HOWL);
DoCast(me, SPELL_ANCESTRAL_WOLF_BUFF, true);
break;
// Move Ryga into position
case 48:
if (Creature* ryga = me->FindNearestCreature(NPC_RYGA,70))
{
if (ryga->IsAlive() && !ryga->IsInCombat())
{
ryga->SetWalk(true);
ryga->SetSpeed(MOVE_WALK, 1.5f);
ryga->GetMotionMaster()->MovePoint(0, 517.340698f, 3885.03975f, 190.455978f, true);
Reset();
}
}
break;
// Ryga Kneels and welcomes spirit wolf
case 50:
if (ryga && ryga->IsAlive() && !ryga->IsInCombat())
ryga->AI()->Talk(SAY_WOLF_WELCOME);
if (Creature* ryga = me->FindNearestCreature(NPC_RYGA,70))
{
if (ryga->IsAlive() && !ryga->IsInCombat())
{
ryga->SetFacingTo(0.776773f);
ryga->SetStandState(UNIT_STAND_STATE_KNEEL);
ryga->AI()->Talk(SAY_WOLF_WELCOME);
Reset();
}
}
break;
// Ryga returns to spawn point
case 51:
if (Creature* ryga = me->FindNearestCreature(NPC_RYGA,70))
{
if (ryga->IsAlive() && !ryga->IsInCombat())
{
float fRetX, fRetY, fRetZ, fRetO;
ryga->GetRespawnPosition(fRetX, fRetY, fRetZ, &fRetO);
ryga->SetHomePosition(fRetX, fRetY, fRetZ, fRetO);
ryga->SetStandState(UNIT_STAND_STATE_STAND);
ryga->GetMotionMaster()->MoveTargetedHome();
Reset();
}
}
break;
}
}

View File

@@ -43,6 +43,7 @@ enum DeathKnightSpells
SPELL_DK_DEATH_AND_DECAY_DAMAGE = 52212,
SPELL_DK_DEATH_COIL_DAMAGE = 47632,
SPELL_DK_DEATH_COIL_HEAL = 47633,
SPELL_DK_DEATH_GRIP = 49560,
SPELL_DK_DEATH_STRIKE_HEAL = 45470,
SPELL_DK_DEATH_STRIKE_ENABLER = 89832,
SPELL_DK_FROST_FEVER = 55095,
@@ -1556,6 +1557,50 @@ class spell_dk_will_of_the_necropolis : public SpellScriptLoader
}
};
// 49576 - Death Grip Initial
class spell_dk_death_grip_initial : public SpellScriptLoader
{
public:
spell_dk_death_grip_initial() : SpellScriptLoader("spell_dk_death_grip_initial") { }
class spell_dk_death_grip_initial_SpellScript : public SpellScript
{
PrepareSpellScript(spell_dk_death_grip_initial_SpellScript);
SpellCastResult CheckCast()
{
Unit* caster = GetCaster();
// Death Grip should not be castable while jumping/falling
if (caster->HasUnitState(UNIT_STATE_JUMPING) || caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING))
return SPELL_FAILED_MOVING;
// Patch 3.3.3 (2010-03-23): Minimum range has been changed to 8 yards in PvP.
Unit* target = GetExplTargetUnit();
if (target && target->GetTypeId() == TYPEID_PLAYER)
if (caster->GetDistance(target) < 8.f)
return SPELL_FAILED_TOO_CLOSE;
return SPELL_CAST_OK;
}
void HandleDummy(SpellEffIndex /*effIndex*/)
{
GetCaster()->CastSpell(GetHitUnit(), SPELL_DK_DEATH_GRIP, true);
}
void Register() override
{
OnCheckCast += SpellCheckCastFn(spell_dk_death_grip_initial_SpellScript::CheckCast);
OnEffectHitTarget += SpellEffectFn(spell_dk_death_grip_initial_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_dk_death_grip_initial_SpellScript();
}
};
void AddSC_deathknight_spell_scripts()
{
new spell_dk_anti_magic_shell_raid();
@@ -1585,4 +1630,5 @@ void AddSC_deathknight_spell_scripts()
new spell_dk_scourge_strike();
new spell_dk_vampiric_blood();
new spell_dk_will_of_the_necropolis();
new spell_dk_death_grip_initial();
}

View File

@@ -1076,9 +1076,12 @@ class spell_q14112_14145_chum_the_water: public SpellScriptLoader
// http://old01.wowhead.com/quest=9452 - Red Snapper - Very Tasty!
enum RedSnapperVeryTasty
{
SPELL_CAST_NET = 29866,
ITEM_RED_SNAPPER = 23614,
SPELL_NEW_SUMMON_TEST = 49214,
ITEM_RED_SNAPPER = 23614,
SPELL_CAST_NET = 29866,
SPELL_NEW_SUMMON_TEST = 49214,
GO_SCHOOL_OF_RED_SNAPPER = 181616
};
class spell_q9452_cast_net: public SpellScriptLoader
@@ -1095,6 +1098,15 @@ class spell_q9452_cast_net: public SpellScriptLoader
return GetCaster()->GetTypeId() == TYPEID_PLAYER;
}
SpellCastResult CheckCast()
{
GameObject* go = GetCaster()->FindNearestGameObject(GO_SCHOOL_OF_RED_SNAPPER, 3.0f);
if (!go || go->GetRespawnTime())
return SPELL_FAILED_REQUIRES_SPELL_FOCUS;
return SPELL_CAST_OK;
}
void HandleDummy(SpellEffIndex /*effIndex*/)
{
Player* caster = GetCaster()->ToPlayer();
@@ -1104,9 +1116,19 @@ class spell_q9452_cast_net: public SpellScriptLoader
caster->CastSpell(caster, SPELL_NEW_SUMMON_TEST, true);
}
void HandleActiveObject(SpellEffIndex effIndex)
{
PreventHitDefaultEffect(effIndex);
GetHitGObj()->SetRespawnTime(roll_chance_i(50) ? 2 * MINUTE : 3 * MINUTE);
GetHitGObj()->Use(GetCaster());
GetHitGObj()->SetLootState(GO_JUST_DEACTIVATED);
}
void Register() override
{
OnCheckCast += SpellCheckCastFn(spell_q9452_cast_net_SpellScript::CheckCast);
OnEffectHit += SpellEffectFn(spell_q9452_cast_net_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
OnEffectHitTarget += SpellEffectFn(spell_q9452_cast_net_SpellScript::HandleActiveObject, EFFECT_1, SPELL_EFFECT_ACTIVATE_OBJECT);
}
};