mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Merge pull request #8725 from krofna/krefixes
Script/AQ: Rewrite Skeram
This commit is contained in:
5
sql/updates/world/2012_12_20_00_world_skeram.sql
Normal file
5
sql/updates/world/2012_12_20_00_world_skeram.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
DELETE FROM `spell_target_position` WHERE id IN (4801,8195,20449);
|
||||
INSERT INTO `spell_target_position` VALUES
|
||||
(4801,531,-8306.68,2060.84,133.062,0),
|
||||
(8195,531,-8344.97,2081.36,125.649,0),
|
||||
(20449,531,-8330.63,2123.14,133.062,0);
|
||||
@@ -16,287 +16,225 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Skeram
|
||||
SD%Complete: 75
|
||||
SDComment: Mind Control buggy.
|
||||
SDCategory: Temple of Ahn'Qiraj
|
||||
EndScriptData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "temple_of_ahnqiraj.h"
|
||||
#include "Group.h"
|
||||
#include "Player.h"
|
||||
|
||||
enum Skeram
|
||||
enum Yells
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_SLAY = 1,
|
||||
SAY_SPLIT = 2,
|
||||
SAY_DEATH = 3,
|
||||
};
|
||||
|
||||
SPELL_ARCANE_EXPLOSION = 25679,
|
||||
enum Spells
|
||||
{
|
||||
SPELL_ARCANE_EXPLOSION = 26192,
|
||||
SPELL_EARTH_SHOCK = 26194,
|
||||
SPELL_TRUE_FULFILLMENT = 785,
|
||||
SPELL_BLINK = 28391
|
||||
SPELL_INITIALIZE_IMAGE = 3730,
|
||||
SPELL_SUMMON_IMAGES = 747
|
||||
};
|
||||
|
||||
class ov_mycoordinates
|
||||
enum Events
|
||||
{
|
||||
public:
|
||||
float x, y, z, r;
|
||||
ov_mycoordinates(float cx, float cy, float cz, float cr)
|
||||
{
|
||||
x = cx; y = cy; z = cz; r = cr;
|
||||
}
|
||||
EVENT_ARCANE_EXPLOSION = 0,
|
||||
EVENT_FULLFILMENT = 1,
|
||||
EVENT_BLINK = 2,
|
||||
EVENT_EARTH_SHOCK = 3
|
||||
};
|
||||
|
||||
uint32 const BlinkSpells[3] = { 4801, 8195, 20449 };
|
||||
|
||||
class boss_skeram : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_skeram() : CreatureScript("boss_skeram") { }
|
||||
public:
|
||||
boss_skeram() : CreatureScript("boss_skeram") { }
|
||||
|
||||
struct boss_skeramAI : public BossAI
|
||||
{
|
||||
boss_skeramAI(Creature* creature) : BossAI(creature, DATA_SKERAM) { }
|
||||
|
||||
void Reset()
|
||||
{
|
||||
_flag = 0;
|
||||
_hpct = 75.0f;
|
||||
me->SetVisible(true);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/)
|
||||
{
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void EnterEvadeMode()
|
||||
{
|
||||
ScriptedAI::EnterEvadeMode();
|
||||
if (me->isSummon())
|
||||
((TempSummon*)me)->UnSummon();
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* creature)
|
||||
{
|
||||
// Shift the boss and images (Get it? *Shift*?)
|
||||
uint8 Rand;
|
||||
if (_flag != 0)
|
||||
{
|
||||
while (_flag & (1 << Rand))
|
||||
Rand = urand(0, 2);
|
||||
DoCast(me, BlinkSpells[Rand]);
|
||||
_flag |= (1 << Rand);
|
||||
_flag |= (1 << 7);
|
||||
}
|
||||
|
||||
while (_flag & (1 << Rand))
|
||||
Rand = urand(0, 2);
|
||||
creature->CastSpell(creature, BlinkSpells[Rand]);
|
||||
_flag |= (1 << Rand);
|
||||
|
||||
if (_flag & (1 << 7))
|
||||
_flag = 0;
|
||||
|
||||
if (Unit* Target = SelectTarget(SELECT_TARGET_RANDOM))
|
||||
creature->AI()->AttackStart(Target);
|
||||
|
||||
float ImageHealthPct;
|
||||
|
||||
if (me->GetHealthPct() < 25.0f)
|
||||
ImageHealthPct = 0.50f;
|
||||
else if (me->GetHealthPct() < 50.0f)
|
||||
ImageHealthPct = 0.20f;
|
||||
else
|
||||
ImageHealthPct = 0.10f;
|
||||
|
||||
creature->SetMaxHealth(me->GetMaxHealth() * ImageHealthPct);
|
||||
creature->SetHealth(creature->GetMaxHealth() * (me->GetHealthPct() / 100.0f));
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/)
|
||||
{
|
||||
if (!me->isSummon())
|
||||
Talk(SAY_DEATH);
|
||||
else
|
||||
me->RemoveCorpse();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/)
|
||||
{
|
||||
_EnterCombat();
|
||||
events.Reset();
|
||||
|
||||
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, urand(6000, 12000));
|
||||
events.ScheduleEvent(EVENT_FULLFILMENT, 15000);
|
||||
events.ScheduleEvent(EVENT_BLINK, urand(30000, 45000));
|
||||
events.ScheduleEvent(EVENT_EARTH_SHOCK, 2000);
|
||||
|
||||
Talk(SAY_AGGRO);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 const diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_ARCANE_EXPLOSION:
|
||||
DoCastAOE(SPELL_ARCANE_EXPLOSION, true);
|
||||
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, urand(8000, 18000));
|
||||
break;
|
||||
case EVENT_FULLFILMENT:
|
||||
// TODO: For some weird reason boss does not cast this
|
||||
// Spell actually works, tested in duel
|
||||
DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true), SPELL_TRUE_FULFILLMENT, true);
|
||||
events.ScheduleEvent(EVENT_FULLFILMENT, urand(20000, 30000));
|
||||
break;
|
||||
case EVENT_BLINK:
|
||||
DoCast(me, BlinkSpells[urand(0, 2)]);
|
||||
DoResetThreat();
|
||||
me->SetVisible(true);
|
||||
events.ScheduleEvent(EVENT_BLINK, urand(10000, 30000));
|
||||
break;
|
||||
case EVENT_EARTH_SHOCK:
|
||||
DoCastVictim(SPELL_EARTH_SHOCK);
|
||||
events.ScheduleEvent(EVENT_EARTH_SHOCK, 2000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!me->isSummon() && me->GetHealthPct() < _hpct)
|
||||
{
|
||||
DoCast(me, SPELL_SUMMON_IMAGES);
|
||||
Talk(SAY_SPLIT);
|
||||
_hpct -= 25.0f;
|
||||
me->SetVisible(false);
|
||||
events.RescheduleEvent(EVENT_BLINK, 2000);
|
||||
}
|
||||
|
||||
if (me->IsWithinMeleeRange(me->getVictim()))
|
||||
{
|
||||
events.RescheduleEvent(EVENT_EARTH_SHOCK, 2000);
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
float _hpct;
|
||||
uint8 _flag;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return new boss_skeramAI (creature);
|
||||
return new boss_skeramAI(creature);
|
||||
}
|
||||
};
|
||||
|
||||
struct boss_skeramAI : public ScriptedAI
|
||||
{
|
||||
boss_skeramAI(Creature* creature) : ScriptedAI(creature)
|
||||
class PlayerOrPetCheck
|
||||
{
|
||||
public:
|
||||
bool operator()(WorldObject* object) const
|
||||
{
|
||||
IsImage = false;
|
||||
if (object->GetTypeId() != TYPEID_PLAYER)
|
||||
if (!object->ToCreature()->isPet())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
uint32 ArcaneExplosion_Timer;
|
||||
uint32 EarthShock_Timer;
|
||||
uint32 FullFillment_Timer;
|
||||
uint32 Blink_Timer;
|
||||
uint32 Invisible_Timer;
|
||||
class spell_skeram_arcane_explosion : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_skeram_arcane_explosion() : SpellScriptLoader("spell_skeram_arcane_explosion") { }
|
||||
|
||||
bool Images75;
|
||||
bool Images50;
|
||||
bool Images25;
|
||||
bool IsImage;
|
||||
bool Invisible;
|
||||
|
||||
void Reset()
|
||||
class spell_skeram_arcane_explosion_SpellScript : public SpellScript
|
||||
{
|
||||
ArcaneExplosion_Timer = urand(6000, 12000);
|
||||
EarthShock_Timer = 2000;
|
||||
FullFillment_Timer = 15000;
|
||||
Blink_Timer = urand(8000, 20000);
|
||||
Invisible_Timer = 500;
|
||||
PrepareSpellScript(spell_skeram_arcane_explosion_SpellScript);
|
||||
|
||||
Images75 = false;
|
||||
Images50 = false;
|
||||
Images25 = false;
|
||||
Invisible = false;
|
||||
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetVisible(true);
|
||||
|
||||
if (IsImage)
|
||||
me->setDeathState(JUST_DIED);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/)
|
||||
{
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/)
|
||||
{
|
||||
if (!IsImage)
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/)
|
||||
{
|
||||
if (IsImage || Images75)
|
||||
return;
|
||||
Talk(SAY_AGGRO);
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
//ArcaneExplosion_Timer
|
||||
if (ArcaneExplosion_Timer <= diff)
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_ARCANE_EXPLOSION);
|
||||
ArcaneExplosion_Timer = urand(8000, 18000);
|
||||
} else ArcaneExplosion_Timer -= diff;
|
||||
|
||||
//If we are within range melee the target
|
||||
if (me->IsWithinMeleeRange(me->getVictim()))
|
||||
{
|
||||
//Make sure our attack is ready and we arn't currently casting
|
||||
if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false))
|
||||
{
|
||||
me->AttackerStateUpdate(me->getVictim());
|
||||
me->resetAttackTimer();
|
||||
}
|
||||
}else
|
||||
{
|
||||
//EarthShock_Timer
|
||||
if (EarthShock_Timer <= diff)
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_EARTH_SHOCK);
|
||||
EarthShock_Timer = 1000;
|
||||
} else EarthShock_Timer -= diff;
|
||||
targets.remove_if(PlayerOrPetCheck());
|
||||
}
|
||||
|
||||
//Blink_Timer
|
||||
if (Blink_Timer <= diff)
|
||||
void Register()
|
||||
{
|
||||
//DoCast(me, SPELL_BLINK);
|
||||
switch (urand(0, 2))
|
||||
{
|
||||
case 0:
|
||||
me->SetPosition(-8340.782227f, 2083.814453f, 125.648788f, 0.0f);
|
||||
DoResetThreat();
|
||||
break;
|
||||
case 1:
|
||||
me->SetPosition(-8341.546875f, 2118.504639f, 133.058151f, 0.0f);
|
||||
DoResetThreat();
|
||||
break;
|
||||
case 2:
|
||||
me->SetPosition(-8318.822266f, 2058.231201f, 133.058151f, 0.0f);
|
||||
DoResetThreat();
|
||||
break;
|
||||
}
|
||||
DoStopAttack();
|
||||
|
||||
Blink_Timer= urand(20000, 40000);
|
||||
} else Blink_Timer -= diff;
|
||||
|
||||
int procent = (int) (me->GetHealthPct() + 0.5f);
|
||||
|
||||
//Summoning 2 Images and teleporting to a random position on 75% health
|
||||
if ((!Images75 && !IsImage) && (procent <= 75 && procent > 70))
|
||||
DoSplit(75);
|
||||
|
||||
//Summoning 2 Images and teleporting to a random position on 50% health
|
||||
if ((!Images50 && !IsImage) && (procent <= 50 && procent > 45))
|
||||
DoSplit(50);
|
||||
|
||||
//Summoning 2 Images and teleporting to a random position on 25% health
|
||||
if ((!Images25 && !IsImage) && (procent <= 25 && procent > 20))
|
||||
DoSplit(25);
|
||||
|
||||
//Invisible_Timer
|
||||
if (Invisible)
|
||||
{
|
||||
if (Invisible_Timer <= diff)
|
||||
{
|
||||
//Making Skeram visible after telporting
|
||||
me->SetVisible(true);
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
|
||||
Invisible_Timer = 2500;
|
||||
Invisible = false;
|
||||
} else Invisible_Timer -= diff;
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_skeram_arcane_explosion_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void DoSplit(int atPercent /* 75 50 25 */)
|
||||
SpellScript* GetSpellScript() const
|
||||
{
|
||||
Talk(SAY_SPLIT);
|
||||
|
||||
ov_mycoordinates *place1 = new ov_mycoordinates(-8340.782227f, 2083.814453f, 125.648788f, 0);
|
||||
ov_mycoordinates *place2 = new ov_mycoordinates(-8341.546875f, 2118.504639f, 133.058151f, 0);
|
||||
ov_mycoordinates *place3 = new ov_mycoordinates(-8318.822266f, 2058.231201f, 133.058151f, 0);
|
||||
|
||||
ov_mycoordinates *bossc=place1, *i1=place2, *i2=place3;
|
||||
|
||||
switch (urand(0, 2))
|
||||
{
|
||||
case 0:
|
||||
bossc=place1;
|
||||
i1=place2;
|
||||
i2=place3;
|
||||
break;
|
||||
case 1:
|
||||
bossc=place2;
|
||||
i1=place1;
|
||||
i2=place3;
|
||||
break;
|
||||
case 2:
|
||||
bossc=place3;
|
||||
i1=place1;
|
||||
i2=place2;
|
||||
break;
|
||||
}
|
||||
|
||||
for (uint16 i = 0; i < 41; ++i)
|
||||
{
|
||||
if (Player* target = CAST_PLR(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)))
|
||||
{
|
||||
if (Group* pGrp = target->GetGroup())
|
||||
for (uint8 ico = 0; ico < TARGETICONCOUNT; ++ico)
|
||||
{
|
||||
//if (grp->m_targetIcons[ico] == me->GetGUID()) -- private member :(
|
||||
pGrp->SetTargetIcon(ico, 0, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
me->RemoveAllAuras();
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetVisible(false);
|
||||
me->SetPosition(bossc->x, bossc->y, bossc->z, bossc->r);
|
||||
Invisible = true;
|
||||
DoResetThreat();
|
||||
DoStopAttack();
|
||||
|
||||
switch (atPercent)
|
||||
{
|
||||
case 75: Images75 = true; break;
|
||||
case 50: Images50 = true; break;
|
||||
case 25: Images25 = true; break;
|
||||
}
|
||||
|
||||
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0);
|
||||
|
||||
Creature* Image1 = me->SummonCreature(15263, i1->x, i1->y, i1->z, i1->r, TEMPSUMMON_CORPSE_DESPAWN, 30000);
|
||||
if (Image1)
|
||||
{
|
||||
Image1->SetMaxHealth(me->GetMaxHealth() / 5);
|
||||
Image1->SetHealth(me->GetHealth() / 5);
|
||||
if (target)
|
||||
Image1->AI()->AttackStart(target);
|
||||
CAST_AI(boss_skeram::boss_skeramAI, Image1->AI())->IsImage = true;
|
||||
}
|
||||
|
||||
Creature* Image2 = me->SummonCreature(15263, i2->x, i2->y, i2->z, i2->r, TEMPSUMMON_CORPSE_DESPAWN, 30000);
|
||||
if (Image2)
|
||||
{
|
||||
Image2->SetMaxHealth(me->GetMaxHealth() / 5);
|
||||
Image2->SetHealth(me->GetHealth() / 5);
|
||||
if (target)
|
||||
Image2->AI()->AttackStart(target);
|
||||
CAST_AI(boss_skeram::boss_skeramAI, Image2->AI())->IsImage = true;
|
||||
}
|
||||
Invisible = true;
|
||||
delete place1;
|
||||
delete place2;
|
||||
delete place3;
|
||||
return new spell_skeram_arcane_explosion_SpellScript();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
void AddSC_boss_skeram()
|
||||
{
|
||||
new boss_skeram();
|
||||
new spell_skeram_arcane_explosion();
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ class npc_glob_of_viscidus : public CreatureScript
|
||||
else
|
||||
{
|
||||
Viscidus->SetHealth(Viscidus->GetHealth() - Viscidus->GetMaxHealth() / 20);
|
||||
Viscidus->GetAI()->DoCast(Viscidus, SPELL_VISCIDUS_SHRINKS);
|
||||
Viscidus->CastSpell(Viscidus, SPELL_VISCIDUS_SHRINKS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user