603 lines
22 KiB
C#
603 lines
22 KiB
C#
/*
|
|
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
|
*
|
|
* 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 Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
using Framework.Constants;
|
|
using Game.AI;
|
|
using Game.Entities;
|
|
using Game.Maps;
|
|
using Game.Scripting;
|
|
|
|
namespace Scripts.Northrend.AzjolNerub.Ahnkahet.JedogaShadowseeker
|
|
{
|
|
struct SpellIds
|
|
{
|
|
public const uint SphereVisual = 56075;
|
|
public const uint GiftOfTheHerald = 56219;
|
|
public const uint CycloneStrike = 56855; // Self
|
|
public const uint LightningBolt = 56891; // 40y
|
|
public const uint Thundershock = 56926; // 30y
|
|
|
|
public const uint RandomLightningVisual = 56327;
|
|
public const uint SacrificeBeam = 56150;
|
|
public const uint SacrificeVisual = 56133;
|
|
}
|
|
|
|
struct TextIds
|
|
{
|
|
public const uint SayAggro = 0;
|
|
public const uint SaySacrifice1 = 1;
|
|
public const uint SaySacrifice2 = 2;
|
|
public const uint SaySlay = 3;
|
|
public const uint SayDeath = 4;
|
|
public const uint SayPreaching = 5;
|
|
}
|
|
struct Misc
|
|
{
|
|
public const int ActionInitiateKilled = 1;
|
|
public const uint DataVolunteerWork = 2;
|
|
|
|
public static Position[] JedogaPosition =
|
|
{
|
|
new Position(372.330994f, -705.278015f, -0.624178f, 5.427970f),
|
|
new Position(372.330994f, -705.278015f, -16.179716f, 5.427970f)
|
|
};
|
|
}
|
|
|
|
[Script]
|
|
class boss_jedoga_shadowseeker : CreatureScript
|
|
{
|
|
public boss_jedoga_shadowseeker() : base("boss_jedoga_shadowseeker") { }
|
|
|
|
public class boss_jedoga_shadowseekerAI : ScriptedAI
|
|
{
|
|
public boss_jedoga_shadowseekerAI(Creature creature) : base(creature)
|
|
{
|
|
instance = creature.GetInstanceScript();
|
|
bFirstTime = true;
|
|
bPreDone = false;
|
|
}
|
|
|
|
void Initialize()
|
|
{
|
|
uiOpFerTimer = RandomHelper.URand(15 * Time.InMilliseconds, 20 * Time.InMilliseconds);
|
|
|
|
uiCycloneTimer = 3 * Time.InMilliseconds;
|
|
uiBoltTimer = 7 * Time.InMilliseconds;
|
|
uiThunderTimer = 12 * Time.InMilliseconds;
|
|
|
|
bOpFerok = false;
|
|
bOpFerokFail = false;
|
|
bOnGround = false;
|
|
bCanDown = false;
|
|
volunteerWork = true;
|
|
}
|
|
|
|
public override void Reset()
|
|
{
|
|
Initialize();
|
|
|
|
DoCast(SpellIds.RandomLightningVisual);
|
|
|
|
if (!bFirstTime)
|
|
instance.SetBossState(DataTypes.JedogaShadowseeker, EncounterState.Fail);
|
|
|
|
instance.SetGuidData(DataTypes.PlJedogaTarget, ObjectGuid.Empty);
|
|
instance.SetGuidData(DataTypes.AddJedogaVictim, ObjectGuid.Empty);
|
|
instance.SetData(DataTypes.JedogaResetInitiands, 0);
|
|
MoveUp();
|
|
|
|
bFirstTime = false;
|
|
}
|
|
|
|
public override void EnterCombat(Unit who)
|
|
{
|
|
if (instance == null || (who.GetTypeId() == TypeId.Unit && who.GetEntry() == AKCreatureIds.JedogaController))
|
|
return;
|
|
|
|
Talk(TextIds.SayAggro);
|
|
me.SetInCombatWithZone();
|
|
instance.SetBossState(DataTypes.JedogaShadowseeker, EncounterState.InProgress);
|
|
}
|
|
|
|
public override void AttackStart(Unit who)
|
|
{
|
|
if (!who || (who.GetTypeId() == TypeId.Unit && who.GetEntry() == AKCreatureIds.JedogaController))
|
|
return;
|
|
|
|
base.AttackStart(who);
|
|
}
|
|
|
|
public override void KilledUnit(Unit Victim)
|
|
{
|
|
if (!Victim || !Victim.IsTypeId(TypeId.Player))
|
|
return;
|
|
|
|
Talk(TextIds.SaySlay);
|
|
}
|
|
|
|
public override void JustDied(Unit killer)
|
|
{
|
|
Talk(TextIds.SayDeath);
|
|
instance.SetBossState(DataTypes.JedogaShadowseeker, EncounterState.Done);
|
|
}
|
|
|
|
public override void DoAction(int action)
|
|
{
|
|
if (action == Misc.ActionInitiateKilled)
|
|
volunteerWork = false;
|
|
}
|
|
|
|
public override uint GetData(uint type)
|
|
{
|
|
if (type == Misc.DataVolunteerWork)
|
|
return volunteerWork ? 1 : 0u;
|
|
|
|
return 0;
|
|
}
|
|
|
|
public override void MoveInLineOfSight(Unit who)
|
|
{
|
|
if (instance == null || !who || (who.IsTypeId(TypeId.Unit) && who.GetEntry() == AKCreatureIds.JedogaController))
|
|
return;
|
|
|
|
if (!bPreDone && who.IsTypeId(TypeId.Player) && me.GetDistance(who) < 100.0f)
|
|
{
|
|
Talk(TextIds.SayPreaching);
|
|
bPreDone = true;
|
|
}
|
|
|
|
if (instance.GetBossState(DataTypes.JedogaShadowseeker) != EncounterState.InProgress || !bOnGround)
|
|
return;
|
|
|
|
if (!me.GetVictim() && me.CanCreatureAttack(who))
|
|
{
|
|
float attackRadius = me.GetAttackDistance(who);
|
|
if (me.IsWithinDistInMap(who, attackRadius) && me.IsWithinLOSInMap(who))
|
|
{
|
|
if (!me.GetVictim())
|
|
{
|
|
who.RemoveAurasByType(AuraType.ModStealth);
|
|
AttackStart(who);
|
|
}
|
|
else
|
|
{
|
|
who.SetInCombatWith(me);
|
|
me.AddThreat(who, 0.0f);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void MoveDown()
|
|
{
|
|
bOpFerokFail = false;
|
|
|
|
instance.SetData(DataTypes.JedogaTriggerSwitch, 0);
|
|
me.GetMotionMaster().MovePoint(1, Misc.JedogaPosition[1]);
|
|
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Normal, false);
|
|
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Magic, false);
|
|
me.RemoveFlag(UnitFields.Flags, UnitFlags.NotSelectable | UnitFlags.NonAttackable);
|
|
|
|
me.RemoveAurasDueToSpell(SpellIds.SphereVisual);
|
|
|
|
bOnGround = true;
|
|
|
|
if (UpdateVictim())
|
|
{
|
|
AttackStart(me.GetVictim());
|
|
me.GetMotionMaster().MoveChase(me.GetVictim());
|
|
}
|
|
else
|
|
{
|
|
Unit target = Global.ObjAccessor.GetUnit(me, instance.GetGuidData(DataTypes.PlJedogaTarget));
|
|
if (target)
|
|
{
|
|
AttackStart(target);
|
|
instance.SetData(DataTypes.JedogaResetInitiands, 0);
|
|
if (instance.GetBossState(DataTypes.JedogaShadowseeker) != EncounterState.InProgress)
|
|
EnterCombat(target);
|
|
}
|
|
else if (!me.IsInCombat())
|
|
EnterEvadeMode();
|
|
}
|
|
}
|
|
|
|
void MoveUp()
|
|
{
|
|
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Normal, true);
|
|
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Magic, true);
|
|
me.SetFlag(UnitFields.Flags, UnitFlags.NotSelectable | UnitFlags.NonAttackable);
|
|
|
|
me.AttackStop();
|
|
me.RemoveAllAuras();
|
|
me.LoadCreaturesAddon();
|
|
me.GetMotionMaster().MovePoint(0, Misc.JedogaPosition[0]);
|
|
|
|
instance.SetData(DataTypes.JedogaTriggerSwitch, 1);
|
|
if (instance.GetBossState(DataTypes.JedogaShadowseeker) == EncounterState.InProgress)
|
|
GetVictimForSacrifice();
|
|
|
|
bOnGround = false;
|
|
uiOpFerTimer = RandomHelper.URand(15 * Time.InMilliseconds, 30 * Time.InMilliseconds);
|
|
}
|
|
|
|
void GetVictimForSacrifice()
|
|
{
|
|
ObjectGuid victim = instance.GetGuidData(DataTypes.AddJedogaInitiand);
|
|
if (!victim.IsEmpty())
|
|
{
|
|
Talk(TextIds.SaySacrifice1);
|
|
instance.SetGuidData(DataTypes.AddJedogaVictim, victim);
|
|
}
|
|
else
|
|
bCanDown = true;
|
|
}
|
|
|
|
void Sacrifice()
|
|
{
|
|
Talk(TextIds.SaySacrifice2);
|
|
|
|
me.InterruptNonMeleeSpells(false);
|
|
DoCast(me, SpellIds.GiftOfTheHerald, false);
|
|
|
|
bOpFerok = false;
|
|
bCanDown = true;
|
|
}
|
|
|
|
public override void UpdateAI(uint diff)
|
|
{
|
|
if (instance.GetBossState(DataTypes.JedogaShadowseeker) != EncounterState.InProgress && instance.GetData(DataTypes.AllInitiandDead) != 0)
|
|
MoveDown();
|
|
|
|
if (bOpFerok && !bOnGround && !bCanDown)
|
|
Sacrifice();
|
|
|
|
if (bOpFerokFail && !bOnGround && !bCanDown)
|
|
bCanDown = true;
|
|
|
|
if (bCanDown)
|
|
{
|
|
MoveDown();
|
|
bCanDown = false;
|
|
}
|
|
|
|
if (bOnGround)
|
|
{
|
|
if (!UpdateVictim())
|
|
return;
|
|
|
|
if (uiCycloneTimer <= diff)
|
|
{
|
|
DoCast(me, SpellIds.CycloneStrike, false);
|
|
uiCycloneTimer = RandomHelper.URand(15 * Time.InMilliseconds, 30 * Time.InMilliseconds);
|
|
}
|
|
else uiCycloneTimer -= diff;
|
|
|
|
if (uiBoltTimer <= diff)
|
|
{
|
|
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 100, true);
|
|
if (target)
|
|
me.CastSpell(target, SpellIds.LightningBolt, false);
|
|
|
|
uiBoltTimer = RandomHelper.URand(15 * Time.InMilliseconds, 30 * Time.InMilliseconds);
|
|
}
|
|
else uiBoltTimer -= diff;
|
|
|
|
if (uiThunderTimer <= diff)
|
|
{
|
|
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 100, true);
|
|
if (target)
|
|
me.CastSpell(target, SpellIds.Thundershock, false);
|
|
|
|
uiThunderTimer = RandomHelper.URand(15 * Time.InMilliseconds, 30 * Time.InMilliseconds);
|
|
}
|
|
else uiThunderTimer -= diff;
|
|
|
|
if (uiOpFerTimer <= diff)
|
|
MoveUp();
|
|
else
|
|
uiOpFerTimer -= diff;
|
|
|
|
DoMeleeAttackIfReady();
|
|
}
|
|
}
|
|
|
|
InstanceScript instance;
|
|
|
|
uint uiOpFerTimer;
|
|
uint uiCycloneTimer;
|
|
uint uiBoltTimer;
|
|
uint uiThunderTimer;
|
|
|
|
bool bPreDone;
|
|
public bool bOpFerok;
|
|
bool bOnGround;
|
|
public bool bOpFerokFail;
|
|
bool bCanDown;
|
|
bool volunteerWork;
|
|
bool bFirstTime;
|
|
}
|
|
|
|
public override CreatureAI GetAI(Creature creature)
|
|
{
|
|
return GetInstanceAI<boss_jedoga_shadowseekerAI>(creature);
|
|
}
|
|
}
|
|
|
|
[Script]
|
|
class npc_jedoga_twilight_volunteer : CreatureScript
|
|
{
|
|
public npc_jedoga_twilight_volunteer() : base("npc_jedoga_initiand") { }
|
|
|
|
class npc_jedoga_twilight_volunteerAI : ScriptedAI
|
|
{
|
|
public npc_jedoga_twilight_volunteerAI(Creature creature) : base(creature)
|
|
{
|
|
Initialize();
|
|
instance = creature.GetInstanceScript();
|
|
}
|
|
|
|
void Initialize()
|
|
{
|
|
bWalking = false;
|
|
bCheckTimer = 2 * Time.InMilliseconds;
|
|
}
|
|
|
|
public override void Reset()
|
|
{
|
|
Initialize();
|
|
|
|
if (instance.GetBossState(DataTypes.JedogaShadowseeker) != EncounterState.InProgress)
|
|
{
|
|
me.RemoveAurasDueToSpell(SpellIds.SphereVisual);
|
|
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Normal, false);
|
|
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Magic, false);
|
|
me.RemoveFlag(UnitFields.Flags, UnitFlags.NotSelectable | UnitFlags.NonAttackable);
|
|
}
|
|
else
|
|
{
|
|
DoCast(me, SpellIds.SphereVisual, false);
|
|
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Normal, true);
|
|
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Magic, true);
|
|
me.SetFlag(UnitFields.Flags, UnitFlags.NotSelectable | UnitFlags.NonAttackable);
|
|
}
|
|
}
|
|
|
|
public override void JustDied(Unit killer)
|
|
{
|
|
if (!killer || instance == null)
|
|
return;
|
|
|
|
if (bWalking)
|
|
{
|
|
Creature boss = ObjectAccessor.GetCreature(me, instance.GetGuidData(DataTypes.JedogaShadowseeker));
|
|
if (boss)
|
|
{
|
|
if (!boss.GetAI<boss_jedoga_shadowseeker.boss_jedoga_shadowseekerAI>().bOpFerok)
|
|
boss.GetAI<boss_jedoga_shadowseeker.boss_jedoga_shadowseekerAI>().bOpFerokFail = true;
|
|
|
|
if (killer.IsTypeId(TypeId.Player))
|
|
boss.GetAI().DoAction(Misc.ActionInitiateKilled);
|
|
}
|
|
|
|
instance.SetGuidData(DataTypes.AddJedogaVictim, ObjectGuid.Empty);
|
|
|
|
bWalking = false;
|
|
}
|
|
if (killer.IsTypeId(TypeId.Player))
|
|
instance.SetGuidData(DataTypes.PlJedogaTarget, killer.GetGUID());
|
|
}
|
|
|
|
public override void EnterCombat(Unit who) { }
|
|
|
|
public override void AttackStart(Unit victim)
|
|
{
|
|
if ((instance.GetBossState(DataTypes.JedogaShadowseeker) == EncounterState.InProgress) || !victim)
|
|
return;
|
|
|
|
base.AttackStart(victim);
|
|
}
|
|
|
|
public override void MoveInLineOfSight(Unit who)
|
|
{
|
|
if ((instance.GetBossState(DataTypes.JedogaShadowseeker) == EncounterState.InProgress) || !who)
|
|
return;
|
|
|
|
base.MoveInLineOfSight(who);
|
|
}
|
|
|
|
public override void MovementInform(MovementGeneratorType uiType, uint uiPointId)
|
|
{
|
|
if (uiType != MovementGeneratorType.Point || instance == null)
|
|
return;
|
|
|
|
switch (uiPointId)
|
|
{
|
|
case 1:
|
|
{
|
|
Creature boss = me.GetMap().GetCreature(instance.GetGuidData(DataTypes.JedogaShadowseeker));
|
|
if (boss)
|
|
{
|
|
boss.GetAI<boss_jedoga_shadowseeker.boss_jedoga_shadowseekerAI>().bOpFerok = true;
|
|
boss.GetAI<boss_jedoga_shadowseeker.boss_jedoga_shadowseekerAI>().bOpFerokFail = false;
|
|
me.KillSelf();
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
public override void UpdateAI(uint diff)
|
|
{
|
|
if (bCheckTimer <= diff)
|
|
{
|
|
if (me.GetGUID() == instance.GetGuidData(DataTypes.AddJedogaVictim) && !bWalking)
|
|
{
|
|
me.RemoveAurasDueToSpell(SpellIds.SphereVisual);
|
|
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Normal, false);
|
|
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Magic, false);
|
|
me.RemoveFlag(UnitFields.Flags, UnitFlags.NotSelectable | UnitFlags.NonAttackable);
|
|
|
|
float distance = me.GetDistance(Misc.JedogaPosition[1]);
|
|
|
|
if (distance < 9.0f)
|
|
me.SetSpeedRate(UnitMoveType.Walk, 0.5f);
|
|
else if (distance < 15.0f)
|
|
me.SetSpeedRate(UnitMoveType.Walk, 0.75f);
|
|
else if (distance < 20.0f)
|
|
me.SetSpeedRate(UnitMoveType.Walk, 1.0f);
|
|
|
|
me.GetMotionMaster().Clear(false);
|
|
me.GetMotionMaster().MovePoint(1, Misc.JedogaPosition[1]);
|
|
bWalking = true;
|
|
}
|
|
if (!bWalking)
|
|
{
|
|
if (instance.GetBossState(DataTypes.JedogaShadowseeker) != EncounterState.InProgress && me.HasAura(SpellIds.SphereVisual))
|
|
{
|
|
me.RemoveAurasDueToSpell(SpellIds.SphereVisual);
|
|
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Normal, false);
|
|
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Magic, false);
|
|
me.RemoveFlag(UnitFields.Flags, UnitFlags.NotSelectable | UnitFlags.NonAttackable);
|
|
}
|
|
if (instance.GetBossState(DataTypes.JedogaShadowseeker) == EncounterState.InProgress && !me.HasAura(SpellIds.SphereVisual))
|
|
{
|
|
DoCast(me, SpellIds.SphereVisual, false);
|
|
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Normal, true);
|
|
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Magic, true);
|
|
me.SetFlag(UnitFields.Flags, UnitFlags.NotSelectable | UnitFlags.NonAttackable);
|
|
}
|
|
}
|
|
bCheckTimer = 2 * Time.InMilliseconds;
|
|
}
|
|
else bCheckTimer -= diff;
|
|
|
|
//Return since we have no target
|
|
if (!UpdateVictim())
|
|
return;
|
|
|
|
DoMeleeAttackIfReady();
|
|
}
|
|
|
|
InstanceScript instance;
|
|
|
|
uint bCheckTimer;
|
|
bool bWalking;
|
|
}
|
|
|
|
public override CreatureAI GetAI(Creature creature)
|
|
{
|
|
return GetInstanceAI<npc_jedoga_twilight_volunteerAI>(creature);
|
|
}
|
|
}
|
|
|
|
[Script]
|
|
class npc_jedoga_controller : CreatureScript
|
|
{
|
|
public npc_jedoga_controller() : base("npc_jedogas_aufseher_trigger") { }
|
|
|
|
class npc_jedoga_controllerAI : ScriptedAI
|
|
{
|
|
public npc_jedoga_controllerAI(Creature creature) : base(creature)
|
|
{
|
|
instance = creature.GetInstanceScript();
|
|
bRemoved = false;
|
|
bRemoved2 = false;
|
|
bCast = false;
|
|
bCast2 = false;
|
|
|
|
SetCombatMovement(false);
|
|
}
|
|
|
|
public override void Reset() { }
|
|
|
|
public override void EnterCombat(Unit who) { }
|
|
|
|
public override void AttackStart(Unit victim) { }
|
|
|
|
public override void MoveInLineOfSight(Unit who) { }
|
|
|
|
public override void UpdateAI(uint diff)
|
|
{
|
|
if (!bRemoved && me.GetPositionX() > 440.0f)
|
|
{
|
|
if (instance.GetBossState(DataTypes.PrinceTaldaram) == EncounterState.Done)
|
|
{
|
|
me.InterruptNonMeleeSpells(true);
|
|
bRemoved = true;
|
|
return;
|
|
}
|
|
if (!bCast)
|
|
{
|
|
//DoCast(me, JedogaShadowseekerConst.SpellBeamVisualJedogasAufseher1, false);
|
|
bCast = true;
|
|
}
|
|
}
|
|
if (!bRemoved2 && me.GetPositionX() < 440.0f)
|
|
{
|
|
if (!bCast2 && instance.GetData(DataTypes.JedogaTriggerSwitch) != 0)
|
|
{
|
|
//DoCast(me, JedogaShadowseekerConst.SpellBeamVisualJedogasAufseher2, false);
|
|
bCast2 = true;
|
|
}
|
|
if (bCast2 && instance.GetData(DataTypes.JedogaTriggerSwitch) == 0)
|
|
{
|
|
me.InterruptNonMeleeSpells(true);
|
|
bCast2 = false;
|
|
}
|
|
if (!bRemoved2 && instance.GetBossState(DataTypes.JedogaShadowseeker) == EncounterState.Done)
|
|
{
|
|
me.InterruptNonMeleeSpells(true);
|
|
bRemoved2 = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
InstanceScript instance;
|
|
|
|
bool bRemoved;
|
|
bool bRemoved2;
|
|
bool bCast;
|
|
bool bCast2;
|
|
}
|
|
|
|
public override CreatureAI GetAI(Creature creature)
|
|
{
|
|
return GetInstanceAI<npc_jedoga_controllerAI>(creature);
|
|
}
|
|
}
|
|
|
|
[Script]
|
|
class achievement_volunteer_work : AchievementCriteriaScript
|
|
{
|
|
public achievement_volunteer_work() : base("achievement_volunteer_work") { }
|
|
|
|
public override bool OnCheck(Player player, Unit target)
|
|
{
|
|
if (!target)
|
|
return false;
|
|
|
|
Creature Jedoga = target.ToCreature();
|
|
if (Jedoga)
|
|
if (Jedoga.GetAI().GetData(Misc.DataVolunteerWork) != 0)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|