More work on scripts.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
|
||||
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
|
||||
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Framework.Constants;
|
||||
@@ -10,102 +10,96 @@ using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Scripts.Pets
|
||||
namespace Scripts.Pets.DeathKnight
|
||||
{
|
||||
namespace DeathKnight
|
||||
[Script]
|
||||
class npc_pet_dk_ebon_gargoyle : CasterAI
|
||||
{
|
||||
struct SpellIds
|
||||
{
|
||||
public const uint SummonGargoyle1 = 49206;
|
||||
public const uint SummonGargoyle2 = 50514;
|
||||
public const uint DismissGargoyle = 50515;
|
||||
public const uint Sanctuary = 54661;
|
||||
}
|
||||
const uint SpellSummonGargoyle1 = 49206;
|
||||
const uint SpellSummonGargoyle2 = 50514;
|
||||
const uint SpellDismissGargoyle = 50515;
|
||||
const uint SpellSanctuary = 54661;
|
||||
|
||||
[Script]
|
||||
class npc_pet_dk_ebon_gargoyle : CasterAI
|
||||
{
|
||||
public npc_pet_dk_ebon_gargoyle(Creature creature) : base(creature) { }
|
||||
public npc_pet_dk_ebon_gargoyle(Creature creature) : base(creature) { }
|
||||
|
||||
public override void InitializeAI()
|
||||
public override void InitializeAI()
|
||||
{
|
||||
base.InitializeAI();
|
||||
ObjectGuid ownerGuid = me.GetOwnerGUID();
|
||||
if (ownerGuid.IsEmpty())
|
||||
return;
|
||||
|
||||
// Find victim of Summon Gargoyle spell
|
||||
List<Unit> targets = new();
|
||||
AnyUnfriendlyUnitInObjectRangeCheck u_check = new(me, me, 30.0f);
|
||||
UnitListSearcher searcher = new(me, targets, u_check);
|
||||
Cell.VisitAllObjects(me, searcher, 30.0f);
|
||||
foreach (Unit target in targets)
|
||||
{
|
||||
base.InitializeAI();
|
||||
ObjectGuid ownerGuid = me.GetOwnerGUID();
|
||||
if (ownerGuid.IsEmpty())
|
||||
return;
|
||||
|
||||
// Find victim of Summon Gargoyle spell
|
||||
List<Unit> targets = new();
|
||||
var u_check = new AnyUnfriendlyUnitInObjectRangeCheck(me, me, 30.0f);
|
||||
var searcher = new UnitListSearcher(me, targets, u_check);
|
||||
Cell.VisitAllObjects(me, searcher, 30.0f);
|
||||
foreach (var target in targets)
|
||||
if (target.HasAura(SpellSummonGargoyle1, ownerGuid))
|
||||
{
|
||||
if (target.HasAura(SpellIds.SummonGargoyle1, ownerGuid))
|
||||
{
|
||||
me.Attack(target, false);
|
||||
break;
|
||||
}
|
||||
me.Attack(target, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
// Stop Feeding Gargoyle when it dies
|
||||
Unit owner = me.GetOwner();
|
||||
if (owner)
|
||||
owner.RemoveAurasDueToSpell(SpellIds.SummonGargoyle2);
|
||||
}
|
||||
|
||||
// Fly away when dismissed
|
||||
public override void SpellHit(WorldObject caster, SpellInfo spellInfo)
|
||||
{
|
||||
if (spellInfo.Id != SpellIds.DismissGargoyle || !me.IsAlive())
|
||||
return;
|
||||
|
||||
Unit owner = me.GetOwner();
|
||||
if (!owner || owner != caster)
|
||||
return;
|
||||
|
||||
// Stop Fighting
|
||||
me.SetUnitFlag(UnitFlags.NonAttackable);
|
||||
|
||||
// Sanctuary
|
||||
me.CastSpell(me, SpellIds.Sanctuary, true);
|
||||
me.SetReactState(ReactStates.Passive);
|
||||
|
||||
//! HACK: Creature's can't have MOVEMENTFLAG_FLYING
|
||||
// Fly Away
|
||||
me.SetCanFly(true);
|
||||
me.SetSpeedRate(UnitMoveType.Flight, 0.75f);
|
||||
me.SetSpeedRate(UnitMoveType.Run, 0.75f);
|
||||
float x = me.GetPositionX() + 20 * (float)Math.Cos(me.GetOrientation());
|
||||
float y = me.GetPositionY() + 20 * (float)Math.Sin(me.GetOrientation());
|
||||
float z = me.GetPositionZ() + 40;
|
||||
me.GetMotionMaster().Clear();
|
||||
me.GetMotionMaster().MovePoint(0, x, y, z);
|
||||
|
||||
// Despawn as soon as possible
|
||||
me.DespawnOrUnsummon(TimeSpan.FromSeconds(4));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_pet_dk_guardian : AggressorAI
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
public npc_pet_dk_guardian(Creature creature) : base(creature) { }
|
||||
// Stop Feeding Gargoyle when it dies
|
||||
Unit owner = me.GetOwner();
|
||||
if (owner != null)
|
||||
owner.RemoveAurasDueToSpell(SpellSummonGargoyle2);
|
||||
}
|
||||
|
||||
public override bool CanAIAttack(Unit target)
|
||||
{
|
||||
if (!target)
|
||||
return false;
|
||||
Unit owner = me.GetOwner();
|
||||
if (owner && !target.IsInCombatWith(owner))
|
||||
return false;
|
||||
return base.CanAIAttack(target);
|
||||
}
|
||||
// Fly away when dismissed
|
||||
public override void SpellHit(WorldObject caster, SpellInfo spellInfo)
|
||||
{
|
||||
if (spellInfo.Id != SpellDismissGargoyle || !me.IsAlive())
|
||||
return;
|
||||
|
||||
Unit owner = me.GetOwner();
|
||||
if (owner == null || owner != caster)
|
||||
return;
|
||||
|
||||
// Stop Fighting
|
||||
me.SetUnitFlag(UnitFlags.NonAttackable);
|
||||
|
||||
// Sanctuary
|
||||
me.CastSpell(me, SpellSanctuary, true);
|
||||
me.SetReactState(ReactStates.Passive);
|
||||
|
||||
//! Hack: Creature's can't have MovementflagFlying
|
||||
// Fly Away
|
||||
me.SetCanFly(true);
|
||||
me.SetSpeedRate(UnitMoveType.Flight, 0.75f);
|
||||
me.SetSpeedRate(UnitMoveType.Run, 0.75f);
|
||||
float x = me.GetPositionX() + 20 * MathF.Cos(me.GetOrientation());
|
||||
float y = me.GetPositionY() + 20 * MathF.Sin(me.GetOrientation());
|
||||
float z = me.GetPositionZ() + 40;
|
||||
me.GetMotionMaster().Clear();
|
||||
me.GetMotionMaster().MovePoint(0, x, y, z);
|
||||
|
||||
// Despawn as soon as possible
|
||||
me.DespawnOrUnsummon(TimeSpan.FromSeconds(4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_pet_dk_guardian : AggressorAI
|
||||
{
|
||||
public npc_pet_dk_guardian(Creature creature) : base(creature) { }
|
||||
|
||||
public override bool CanAIAttack(Unit target)
|
||||
{
|
||||
if (target == null)
|
||||
return false;
|
||||
|
||||
Unit owner = me.GetOwner();
|
||||
if (owner != null && !target.IsInCombatWith(owner))
|
||||
return false;
|
||||
|
||||
return base.CanAIAttack(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
+229
-177
@@ -1,200 +1,252 @@
|
||||
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
|
||||
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
|
||||
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Dynamic;
|
||||
using Game.AI;
|
||||
using Game.Entities;
|
||||
using Game.Scripting;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Scripts.Pets
|
||||
namespace Scripts.Pets.Generic
|
||||
{
|
||||
namespace Generic
|
||||
[Script]
|
||||
class npc_pet_gen_pandaren_monk : NullCreatureAI
|
||||
{
|
||||
struct SpellIds
|
||||
const uint SpellPandarenMonk = 69800;
|
||||
|
||||
Action<TaskContext> focusAction;
|
||||
|
||||
public npc_pet_gen_pandaren_monk(Creature creature) : base(creature)
|
||||
{
|
||||
//Mojo
|
||||
public const uint FeelingFroggy = 43906;
|
||||
public const uint SeductionVisual = 43919;
|
||||
|
||||
//SoulTrader
|
||||
public const uint EtherealOnSummon = 50052;
|
||||
public const uint EtherealPetRemoveAura = 50055;
|
||||
|
||||
// LichPet
|
||||
public const uint LichPetAura = 69732;
|
||||
public const uint LichPetAuraOnkill = 69731;
|
||||
public const uint LichPetEmote = 70049;
|
||||
}
|
||||
|
||||
struct CreatureIds
|
||||
{
|
||||
// LichPet
|
||||
public const uint LichPet = 36979;
|
||||
}
|
||||
|
||||
struct TextIds
|
||||
{
|
||||
//Mojo
|
||||
public const uint SayMojo = 0;
|
||||
|
||||
//SoulTrader
|
||||
public const uint SaySoulTraderInto = 0;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_pet_gen_soul_trader : ScriptedAI
|
||||
{
|
||||
public npc_pet_gen_soul_trader(Creature creature) : base(creature) { }
|
||||
|
||||
public override void OnDespawn()
|
||||
focusAction = task =>
|
||||
{
|
||||
Unit owner = me.GetOwner();
|
||||
Unit owner = me.GetCharmerOrOwner();
|
||||
if (owner != null)
|
||||
DoCast(owner, SpellIds.EtherealPetRemoveAura);
|
||||
}
|
||||
me.SetFacingToObject(owner);
|
||||
|
||||
public override void JustAppeared()
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(1), _ =>
|
||||
{
|
||||
me.HandleEmoteCommand(Emote.OneshotBow);
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(1), _ =>
|
||||
{
|
||||
Unit owner = me.GetCharmerOrOwner();
|
||||
if (owner != null)
|
||||
me.GetMotionMaster().MoveFollow(owner, SharedConst.PetFollowDist, SharedConst.PetFollowAngle);
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(1), focusAction);
|
||||
}
|
||||
|
||||
public override void EnterEvadeMode(EvadeReason why)
|
||||
{
|
||||
if (!_EnterEvadeMode(why))
|
||||
return;
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
public override void ReceiveEmote(Player player, TextEmotes emote)
|
||||
{
|
||||
me.InterruptSpell(CurrentSpellTypes.Channeled);
|
||||
me.StopMoving();
|
||||
|
||||
switch (emote)
|
||||
{
|
||||
Talk(TextIds.SaySoulTraderInto);
|
||||
|
||||
Unit owner = me.GetOwner();
|
||||
if (owner != null)
|
||||
DoCast(owner, SpellIds.EtherealOnSummon);
|
||||
|
||||
base.JustAppeared();
|
||||
case TextEmotes.Bow:
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(1), focusAction);
|
||||
break;
|
||||
case TextEmotes.Drink:
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(1), _ => me.CastSpell(me, SpellPandarenMonk, false));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
[Script] // 69735 - Lich Pet OnSummon
|
||||
class spell_gen_lich_pet_onsummon : SpellScript
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.LichPetAura);
|
||||
}
|
||||
_scheduler.Update(diff);
|
||||
|
||||
void HandleScriptEffect(uint effIndex)
|
||||
{
|
||||
Unit target = GetHitUnit();
|
||||
target.CastSpell(target, SpellIds.LichPetAura, true);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleScriptEffect, 0, SpellEffectName.ScriptEffect));
|
||||
}
|
||||
}
|
||||
|
||||
[Script] // 69736 - Lich Pet Aura Remove
|
||||
class spell_gen_lich_pet_aura_remove : SpellScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.LichPetAura);
|
||||
}
|
||||
|
||||
void HandleScriptEffect(uint effIndex)
|
||||
{
|
||||
GetHitUnit().RemoveAurasDueToSpell(SpellIds.LichPetAura);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleScriptEffect, 0, SpellEffectName.ScriptEffect));
|
||||
}
|
||||
}
|
||||
|
||||
[Script] // 69732 - Lich Pet Aura
|
||||
class spell_gen_lich_pet_aura : AuraScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.LichPetAuraOnkill);
|
||||
}
|
||||
|
||||
bool CheckProc(ProcEventInfo eventInfo)
|
||||
{
|
||||
return eventInfo.GetProcTarget().IsPlayer();
|
||||
}
|
||||
|
||||
void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
|
||||
List<TempSummon> minionList = new();
|
||||
GetUnitOwner().GetAllMinionsByEntry(minionList, CreatureIds.LichPet);
|
||||
foreach (Creature minion in minionList)
|
||||
if (minion.IsAIEnabled())
|
||||
minion.GetAI().DoCastSelf(SpellIds.LichPetAuraOnkill);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
DoCheckProc.Add(new CheckProcHandler(CheckProc));
|
||||
OnEffectProc.Add(new EffectProcHandler(HandleProc, 0, AuraType.ProcTriggerSpell));
|
||||
}
|
||||
}
|
||||
|
||||
[Script] // 70050 - [DND] Lich Pet
|
||||
class spell_pet_gen_lich_pet_periodic_emote : AuraScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.LichPetEmote);
|
||||
}
|
||||
|
||||
void OnPeriodic(AuraEffect aurEff)
|
||||
{
|
||||
// The chance to cast this spell is not 100%.
|
||||
// Triggered spell roots creature for 3 sec and plays anim and sound (doesn't require any script).
|
||||
// Emote and sound never shows up in sniffs because both comes from spell visual directly.
|
||||
// Both 69683 and 70050 can trigger spells at once and are not linked together in any way.
|
||||
// Effect of 70050 is overlapped by effect of 69683 but not instantly (69683 is a series of spell casts, takes longer to execute).
|
||||
// However, for some reason emote is not played if creature is idle and only if creature is moving or is already rooted.
|
||||
// For now it's scripted manually in script below to play emote always.
|
||||
if (RandomHelper.randChance(50))
|
||||
GetTarget().CastSpell(GetTarget(), SpellIds.LichPetEmote, true);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectPeriodic.Add(new EffectPeriodicHandler(OnPeriodic, 0, AuraType.PeriodicTriggerSpell));
|
||||
}
|
||||
}
|
||||
|
||||
[Script] // 70049 - [DND] Lich Pet
|
||||
class spell_pet_gen_lich_pet_emote : AuraScript
|
||||
{
|
||||
void AfterApply(AuraEffect aurEff, AuraEffectHandleModes mode)
|
||||
{
|
||||
GetTarget().HandleEmoteCommand(Emote.OneshotCustomSpell01);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
AfterEffectApply.Add(new EffectApplyHandler(AfterApply, 0, AuraType.ModRoot, AuraEffectHandleModes.Real));
|
||||
}
|
||||
}
|
||||
|
||||
[Script] // 69682 - Lil' K.T. Focus
|
||||
class spell_pet_gen_lich_pet_focus : SpellScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo((uint)spellInfo.GetEffect(0).CalcValue());
|
||||
}
|
||||
|
||||
void HandleScript(uint effIndex)
|
||||
{
|
||||
GetCaster().CastSpell(GetHitUnit(), (uint)GetEffectValue());
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleScript, 0, SpellEffectName.ScriptEffect));
|
||||
}
|
||||
Unit owner = me.GetCharmerOrOwner();
|
||||
if (owner != null)
|
||||
if (!me.IsWithinDist(owner, 30.0f))
|
||||
me.InterruptSpell(CurrentSpellTypes.Channeled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_pet_gen_soul_trader : ScriptedAI
|
||||
{
|
||||
const uint SaySoulTraderIntro = 0;
|
||||
|
||||
const uint SpellEtherealOnsummon = 50052;
|
||||
const uint SpellEtherealPetRemoveAura = 50055;
|
||||
|
||||
public npc_pet_gen_soul_trader(Creature creature) : base(creature) { }
|
||||
|
||||
public override void OnDespawn()
|
||||
{
|
||||
Unit owner = me.GetOwner();
|
||||
if (owner != null)
|
||||
DoCast(owner, SpellEtherealPetRemoveAura);
|
||||
}
|
||||
|
||||
public override void JustAppeared()
|
||||
{
|
||||
Talk(SaySoulTraderIntro);
|
||||
Unit owner = me.GetOwner();
|
||||
if (owner != null)
|
||||
DoCast(owner, SpellEtherealOnsummon);
|
||||
|
||||
base.JustAppeared();
|
||||
}
|
||||
}
|
||||
|
||||
[Script] // 69735 - Lich Pet OnSummon
|
||||
class spell_pet_gen_lich_pet_onsummon : SpellScript
|
||||
{
|
||||
const uint SpellLichPetAura = 69732;
|
||||
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo(SpellLichPetAura);
|
||||
}
|
||||
|
||||
void HandleScript(uint effIndex)
|
||||
{
|
||||
Unit target = GetHitUnit();
|
||||
target.CastSpell(target, SpellLichPetAura, true);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect));
|
||||
}
|
||||
}
|
||||
|
||||
[Script] // 69736 - Lich Pet Aura Remove
|
||||
class spell_pet_gen_lich_pet_aura_Remove : SpellScript
|
||||
{
|
||||
const uint SpellLichPetAura = 69732;
|
||||
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo(SpellLichPetAura);
|
||||
}
|
||||
|
||||
void HandleScript(uint effIndex)
|
||||
{
|
||||
GetHitUnit().RemoveAurasDueToSpell(SpellLichPetAura);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect));
|
||||
}
|
||||
}
|
||||
|
||||
[Script] // 69732 - Lich Pet Aura
|
||||
class spell_pet_gen_lich_pet_AuraScript : AuraScript
|
||||
{
|
||||
const uint SpellLichPetAuraOnkill = 69731;
|
||||
|
||||
const uint NpcLichPet = 36979;
|
||||
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo(SpellLichPetAuraOnkill);
|
||||
}
|
||||
|
||||
bool CheckProc(ProcEventInfo eventInfo)
|
||||
{
|
||||
return eventInfo.GetProcTarget().IsPlayer();
|
||||
}
|
||||
|
||||
void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
|
||||
Unit owner = GetUnitOwner();
|
||||
|
||||
List<TempSummon> minionList = new();
|
||||
owner.GetAllMinionsByEntry(minionList, NpcLichPet);
|
||||
foreach (TempSummon minion in minionList)
|
||||
owner.CastSpell(minion, SpellLichPetAuraOnkill, true);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
DoCheckProc.Add(new(CheckProc));
|
||||
OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell));
|
||||
}
|
||||
}
|
||||
|
||||
[Script] // 70050 - [Dnd] Lich Pet
|
||||
class spell_pet_gen_lich_pet_periodic_emote : AuraScript
|
||||
{
|
||||
const uint SpellLichPetEmote = 70049;
|
||||
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo(SpellLichPetEmote);
|
||||
}
|
||||
|
||||
void OnPeriodic(AuraEffect aurEff)
|
||||
{
|
||||
// The chance to cast this spell is not 100%.
|
||||
// Triggered spell roots creature for 3 sec and plays anim and sound (doesn't require any script).
|
||||
// Emote and sound never shows up in sniffs because both comes from spell visual directly.
|
||||
// Both 69683 and 70050 can trigger spells at once and are not linked together in any way.
|
||||
// Effect of 70050 is overlapped by effect of 69683 but not instantly (69683 is a series of spell casts, takes longer to execute).
|
||||
// However, for some reason emote is not played if creature is idle and only if creature is moving or is already rooted.
|
||||
// For now it's scripted manually in script below to play emote always.
|
||||
if (RandomHelper.randChance(50))
|
||||
GetTarget().CastSpell(GetTarget(), SpellLichPetEmote, true);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectPeriodic.Add(new(OnPeriodic, 0, AuraType.PeriodicTriggerSpell));
|
||||
}
|
||||
}
|
||||
|
||||
[Script] // 70049 - [Dnd] Lich Pet
|
||||
class spell_pet_gen_lich_pet_emote : AuraScript
|
||||
{
|
||||
void AfterApply(AuraEffect aurEff, AuraEffectHandleModes mode)
|
||||
{
|
||||
GetTarget().HandleEmoteCommand(Emote.OneshotCustomSpell01);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
AfterEffectApply.Add(new(AfterApply, 0, AuraType.ModRoot, AuraEffectHandleModes.Real));
|
||||
}
|
||||
}
|
||||
|
||||
[Script] // 69682 - Lil' K.T. Focus
|
||||
class spell_pet_gen_lich_pet_focus : SpellScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo((uint)spellInfo.GetEffect(0).CalcValue());
|
||||
}
|
||||
|
||||
void HandleScript(uint effIndex)
|
||||
{
|
||||
GetCaster().CastSpell(GetHitUnit(), (uint)GetEffectValue());
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
|
||||
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
|
||||
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Framework.Constants;
|
||||
@@ -6,108 +6,99 @@ using Game.AI;
|
||||
using Game.Combat;
|
||||
using Game.Entities;
|
||||
using Game.Scripting;
|
||||
using Game.Spells;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Scripts.Pets
|
||||
namespace Scripts.Pets.Hunter
|
||||
{
|
||||
namespace Hunter
|
||||
[Script]
|
||||
class npc_pet_hunter_snake_trap : ScriptedAI
|
||||
{
|
||||
struct SpellIds
|
||||
const uint SpellHunterCripplingPoison = 30981; // Viper
|
||||
const uint SpellHunterDeadlyPoisonPassive = 34657; // Venomous Snake
|
||||
const uint SpellHunterMindNumbingPoison = 25810; // Viper
|
||||
|
||||
const uint NpcHunterViper = 19921;
|
||||
|
||||
bool _isViper;
|
||||
uint _spellTimer;
|
||||
|
||||
public npc_pet_hunter_snake_trap(Creature creature) : base(creature) { }
|
||||
|
||||
public override void JustEngagedWith(Unit who) { }
|
||||
|
||||
public override void JustAppeared()
|
||||
{
|
||||
public const uint CripplingPoison = 30981; // Viper
|
||||
public const uint DeadlyPoisonPassive = 34657; // Venomous Snake
|
||||
public const uint MindNumbingPoison = 25810; // Viper
|
||||
_isViper = me.GetEntry() == NpcHunterViper ? true : false;
|
||||
|
||||
me.SetMaxHealth((uint)(107 * (me.GetLevel() - 40) * 0.025f));
|
||||
// Add delta to make them not all hit the same time
|
||||
me.SetBaseAttackTime(WeaponAttackType.BaseAttack, me.GetBaseAttackTime(WeaponAttackType.BaseAttack) + RandomHelper.URand(0, 6));
|
||||
|
||||
if (!_isViper && !me.HasAura(SpellHunterDeadlyPoisonPassive))
|
||||
DoCast(me, SpellHunterDeadlyPoisonPassive, true);
|
||||
}
|
||||
|
||||
struct CreatureIds
|
||||
// Redefined for random target selection:
|
||||
public override void MoveInLineOfSight(Unit who) { }
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
public const int Viper = 19921;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_pet_hunter_snake_trap : ScriptedAI
|
||||
{
|
||||
public npc_pet_hunter_snake_trap(Creature creature) : base(creature) { }
|
||||
|
||||
public override void JustEngagedWith(Unit who) { }
|
||||
|
||||
public override void JustAppeared()
|
||||
{
|
||||
_isViper = me.GetEntry() == CreatureIds.Viper ? true : false;
|
||||
|
||||
me.SetMaxHealth((uint)(107 * (me.GetLevel() - 40) * 0.025f));
|
||||
// Add delta to make them not all hit the same time
|
||||
me.SetBaseAttackTime(WeaponAttackType.BaseAttack, me.GetBaseAttackTime(WeaponAttackType.BaseAttack) + RandomHelper.URand(0, 6) * Time.InMilliseconds);
|
||||
|
||||
if (!_isViper && !me.HasAura(SpellIds.DeadlyPoisonPassive))
|
||||
DoCast(me, SpellIds.DeadlyPoisonPassive, new CastSpellExtraArgs(true));
|
||||
if (me.GetVictim() != null && me.GetVictim().HasBreakableByDamageCrowdControlAura())
|
||||
{ // don't break cc
|
||||
me.GetThreatManager().ClearFixate();
|
||||
me.InterruptNonMeleeSpells(false);
|
||||
me.AttackStop();
|
||||
return;
|
||||
}
|
||||
|
||||
// Redefined for random target selection:
|
||||
public override void MoveInLineOfSight(Unit who) { }
|
||||
if (me.IsSummon() && me.GetThreatManager().GetFixateTarget() == null)
|
||||
{ // find new target
|
||||
Unit summoner = me.ToTempSummon().GetSummonerUnit();
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (me.GetVictim() && me.GetVictim().HasBreakableByDamageCrowdControlAura())
|
||||
{ // don't break cc
|
||||
me.GetThreatManager().ClearFixate();
|
||||
me.InterruptNonMeleeSpells(false);
|
||||
me.AttackStop();
|
||||
return;
|
||||
List<Unit> targets = new();
|
||||
|
||||
void addTargetIfValid(CombatReference refe)
|
||||
{
|
||||
Unit enemy = refe.GetOther(summoner);
|
||||
if (!enemy.HasBreakableByDamageCrowdControlAura() && me.CanCreatureAttack(enemy) && me.IsWithinDistInMap(enemy, me.GetAttackDistance(enemy)))
|
||||
targets.Add(enemy);
|
||||
}
|
||||
|
||||
if (me.IsSummon() && !me.GetThreatManager().GetFixateTarget())
|
||||
{ // find new target
|
||||
Unit summoner = me.ToTempSummon().GetSummonerUnit();
|
||||
List<Unit> targets = new();
|
||||
foreach (var pair in summoner.GetCombatManager().GetPvPCombatRefs())
|
||||
addTargetIfValid(pair.Value);
|
||||
|
||||
void addTargetIfValid(CombatReference refe)
|
||||
{
|
||||
Unit enemy = refe.GetOther(summoner);
|
||||
if (!enemy.HasBreakableByDamageCrowdControlAura() && me.CanCreatureAttack(enemy) && me.IsWithinDistInMap(enemy, me.GetAttackDistance(enemy)))
|
||||
targets.Add(enemy);
|
||||
}
|
||||
|
||||
foreach (var pair in summoner.GetCombatManager().GetPvPCombatRefs())
|
||||
if (targets.Empty())
|
||||
foreach (var pair in summoner.GetCombatManager().GetPvECombatRefs())
|
||||
addTargetIfValid(pair.Value);
|
||||
|
||||
if (targets.Empty())
|
||||
foreach (var pair in summoner.GetCombatManager().GetPvECombatRefs())
|
||||
addTargetIfValid(pair.Value);
|
||||
foreach (Unit target in targets)
|
||||
me.EngageWithTarget(target);
|
||||
|
||||
foreach (Unit target in targets)
|
||||
me.EngageWithTarget(target);
|
||||
|
||||
if (!targets.Empty())
|
||||
{
|
||||
Unit target = targets.SelectRandom();
|
||||
me.GetThreatManager().FixateTarget(target);
|
||||
}
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
// Viper
|
||||
if (_isViper)
|
||||
if (!targets.Empty())
|
||||
{
|
||||
if (_spellTimer <= diff)
|
||||
{
|
||||
if (RandomHelper.URand(0, 2) == 0) // 33% chance to cast
|
||||
DoCastVictim(RandomHelper.RAND(SpellIds.MindNumbingPoison, SpellIds.CripplingPoison));
|
||||
|
||||
_spellTimer = 3000;
|
||||
}
|
||||
else
|
||||
_spellTimer -= diff;
|
||||
Unit target = targets.SelectRandom();
|
||||
me.GetThreatManager().FixateTarget(target);
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
bool _isViper;
|
||||
uint _spellTimer;
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
// Viper
|
||||
if (_isViper)
|
||||
{
|
||||
if (_spellTimer <= diff)
|
||||
{
|
||||
if (RandomHelper.URand(0, 2) == 0) // 33% chance to cast
|
||||
DoCastVictim(RandomHelper.RAND(SpellHunterMindNumbingPoison, SpellHunterCripplingPoison));
|
||||
|
||||
_spellTimer = 3000;
|
||||
}
|
||||
else
|
||||
_spellTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+131
-145
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
|
||||
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
|
||||
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Framework.Constants;
|
||||
@@ -6,175 +6,161 @@ using Game.AI;
|
||||
using Game.Entities;
|
||||
using Game.Scripting;
|
||||
|
||||
namespace Scripts.Pets
|
||||
namespace Scripts.Pets.Mage
|
||||
{
|
||||
namespace Mage
|
||||
[Script]
|
||||
class npc_pet_mage_mirror_image : ScriptedAI
|
||||
{
|
||||
struct SpellIds
|
||||
const uint SpellMageCloneMe = 45204;
|
||||
const uint SpellMageFrostBolt = 59638;
|
||||
const uint SpellMageFireBlast = 59637;
|
||||
|
||||
const uint TimerMirrorImageFireBlast = 6500;
|
||||
float ChaseDistance = 35.0f;
|
||||
|
||||
uint _fireBlastTimer = 0;
|
||||
|
||||
public npc_pet_mage_mirror_image(Creature creature) : base(creature) { }
|
||||
|
||||
public override void InitializeAI()
|
||||
{
|
||||
public const uint CloneMe = 45204;
|
||||
public const uint MastersThreatList = 58838;
|
||||
public const uint MageFrostBolt = 59638;
|
||||
public const uint MageFireBlast = 59637;
|
||||
Unit owner = me.GetOwner();
|
||||
if (owner == null)
|
||||
return;
|
||||
|
||||
// here mirror image casts on summoner spell (not present in client dbc) 49866
|
||||
// here should be auras (not present in client dbc): 35657, 35658, 35659, 35660 selfcast by mirror images (stats related?)
|
||||
// Clone Me!
|
||||
owner.CastSpell(me, SpellMageCloneMe, true);
|
||||
}
|
||||
|
||||
struct MiscConst
|
||||
// custom UpdateVictim implementation to handle special target selection
|
||||
// we prioritize between things that are in combat with owner based on the owner's threat to them
|
||||
bool UpdateVictimCustom()
|
||||
{
|
||||
public const uint TimerMirrorImageInit = 0;
|
||||
public const uint TimerMirrorImageFrostBolt = 4000;
|
||||
public const uint TimerMirrorImageFireBlast = 6000;
|
||||
}
|
||||
Unit owner = me.GetOwner();
|
||||
if (owner == null)
|
||||
return false;
|
||||
|
||||
[Script]
|
||||
class npc_pet_mage_mirror_image : ScriptedAI
|
||||
{
|
||||
const float CHASE_DISTANCE = 35.0f;
|
||||
if (!me.HasUnitState(UnitState.Casting) && !me.IsInCombat() && !owner.IsInCombat())
|
||||
return false;
|
||||
|
||||
uint _fireBlastTimer = 0;
|
||||
|
||||
public npc_pet_mage_mirror_image(Creature creature) : base(creature) { }
|
||||
|
||||
public override void InitializeAI()
|
||||
Unit currentTarget = me.GetVictim();
|
||||
if (currentTarget != null && !CanAIAttack(currentTarget))
|
||||
{
|
||||
Unit owner = me.GetOwner();
|
||||
if (owner == null)
|
||||
return;
|
||||
|
||||
// here mirror image casts on summoner spell (not present in client dbc) 49866
|
||||
// here should be auras (not present in client dbc): 35657, 35658, 35659, 35660 selfcast by mirror images (stats related?)
|
||||
// Clone Me!
|
||||
owner.CastSpell(me, SpellIds.CloneMe, true);
|
||||
me.InterruptNonMeleeSpells(true); // do not finish casting on invalid targets
|
||||
me.AttackStop();
|
||||
currentTarget = null;
|
||||
}
|
||||
|
||||
// custom UpdateVictim implementation to handle special target selection
|
||||
// we prioritize between things that are in combat with owner based on the owner's threat to them
|
||||
new bool UpdateVictim()
|
||||
{
|
||||
Unit owner = me.GetOwner();
|
||||
if (owner == null)
|
||||
return false;
|
||||
|
||||
if (!me.HasUnitState(UnitState.Casting) && !me.IsInCombat() && !owner.IsInCombat())
|
||||
return false;
|
||||
|
||||
Unit currentTarget = me.GetVictim();
|
||||
if (currentTarget && !CanAIAttack(currentTarget))
|
||||
{
|
||||
me.InterruptNonMeleeSpells(true); // do not finish casting on invalid targets
|
||||
me.AttackStop();
|
||||
currentTarget = null;
|
||||
}
|
||||
|
||||
// don't reselect if we're currently casting anyway
|
||||
if (currentTarget && me.HasUnitState(UnitState.Casting))
|
||||
return true;
|
||||
|
||||
Unit selectedTarget = null;
|
||||
var mgr = owner.GetCombatManager();
|
||||
if (mgr.HasPvPCombat())
|
||||
{ // select pvp target
|
||||
float minDistance = 0.0f;
|
||||
foreach (var pair in mgr.GetPvPCombatRefs())
|
||||
{
|
||||
Unit target = pair.Value.GetOther(owner);
|
||||
if (!target.IsPlayer())
|
||||
continue;
|
||||
|
||||
if (!CanAIAttack(target))
|
||||
continue;
|
||||
|
||||
float dist = owner.GetDistance(target);
|
||||
if (!selectedTarget || dist < minDistance)
|
||||
{
|
||||
selectedTarget = target;
|
||||
minDistance = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!selectedTarget)
|
||||
{ // select pve target
|
||||
float maxThreat = 0.0f;
|
||||
foreach (var pair in mgr.GetPvECombatRefs())
|
||||
{
|
||||
Unit target = pair.Value.GetOther(owner);
|
||||
if (!CanAIAttack(target))
|
||||
continue;
|
||||
|
||||
float threat = target.GetThreatManager().GetThreat(owner);
|
||||
if (threat >= maxThreat)
|
||||
{
|
||||
selectedTarget = target;
|
||||
maxThreat = threat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!selectedTarget)
|
||||
{
|
||||
EnterEvadeMode(EvadeReason.NoHostiles);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (selectedTarget != me.GetVictim())
|
||||
AttackStartCaster(selectedTarget, CHASE_DISTANCE);
|
||||
// don't reselect if we're currently casting anyway
|
||||
if (currentTarget != null && me.HasUnitState(UnitState.Casting))
|
||||
return true;
|
||||
|
||||
Unit selectedTarget = null;
|
||||
var mgr = owner.GetCombatManager();
|
||||
if (mgr.HasPvPCombat())
|
||||
{ // select pvp target
|
||||
float minDistance = 0.0f;
|
||||
foreach (var pair in mgr.GetPvPCombatRefs())
|
||||
{
|
||||
Unit target = pair.Value.GetOther(owner);
|
||||
if (!target.IsPlayer())
|
||||
continue;
|
||||
if (!CanAIAttack(target))
|
||||
continue;
|
||||
|
||||
float dist = owner.GetDistance(target);
|
||||
if (selectedTarget == null || dist < minDistance)
|
||||
{
|
||||
selectedTarget = target;
|
||||
minDistance = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
if (selectedTarget == null)
|
||||
{ // select pve target
|
||||
float maxThreat = 0.0f;
|
||||
foreach (var pair in mgr.GetPvECombatRefs())
|
||||
{
|
||||
Unit target = pair.Value.GetOther(owner);
|
||||
if (!CanAIAttack(target))
|
||||
continue;
|
||||
|
||||
float threat = target.GetThreatManager().GetThreat(owner);
|
||||
if (threat >= maxThreat)
|
||||
{
|
||||
selectedTarget = target;
|
||||
maxThreat = threat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedTarget == null)
|
||||
{
|
||||
Unit owner = me.GetOwner();
|
||||
if (owner == null)
|
||||
{
|
||||
me.DespawnOrUnsummon();
|
||||
return;
|
||||
}
|
||||
EnterEvadeMode(EvadeReason.NoHostiles);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_fireBlastTimer != 0)
|
||||
{
|
||||
if (_fireBlastTimer <= diff)
|
||||
_fireBlastTimer = 0;
|
||||
else
|
||||
_fireBlastTimer -= diff;
|
||||
}
|
||||
if (selectedTarget != me.GetVictim())
|
||||
AttackStartCaster(selectedTarget, ChaseDistance);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
Unit owner = me.GetOwner();
|
||||
if (owner == null)
|
||||
{
|
||||
me.DespawnOrUnsummon();
|
||||
return;
|
||||
}
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
if (_fireBlastTimer == 0)
|
||||
{
|
||||
DoCastVictim(SpellIds.MageFireBlast);
|
||||
_fireBlastTimer = MiscConst.TimerMirrorImageFireBlast;
|
||||
}
|
||||
if (_fireBlastTimer != 0)
|
||||
{
|
||||
if (_fireBlastTimer <= diff)
|
||||
_fireBlastTimer = 0;
|
||||
else
|
||||
DoCastVictim(SpellIds.MageFrostBolt);
|
||||
_fireBlastTimer -= diff;
|
||||
}
|
||||
|
||||
public override bool CanAIAttack(Unit who)
|
||||
if (!UpdateVictimCustom())
|
||||
return;
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
if (_fireBlastTimer == 0)
|
||||
{
|
||||
Unit owner = me.GetOwner();
|
||||
return owner && who.IsAlive() && me.IsValidAttackTarget(who) &&
|
||||
!who.HasBreakableByDamageCrowdControlAura() &&
|
||||
who.IsInCombatWith(owner) && CanAIAttack(who);
|
||||
DoCastVictim(SpellMageFireBlast);
|
||||
_fireBlastTimer = TimerMirrorImageFireBlast;
|
||||
}
|
||||
else
|
||||
DoCastVictim(SpellMageFrostBolt);
|
||||
}
|
||||
|
||||
// Do not reload Creature templates on evade mode enter - prevent visual lost
|
||||
public override void EnterEvadeMode(EvadeReason why)
|
||||
public override bool CanAIAttack(Unit who)
|
||||
{
|
||||
Unit owner = me.GetOwner();
|
||||
return owner != null && who.IsAlive() && me.IsValidAttackTarget(who) &&
|
||||
!who.HasBreakableByDamageCrowdControlAura() &&
|
||||
who.IsInCombatWith(owner) && base.CanAIAttack(who);
|
||||
}
|
||||
|
||||
// Do not reload Creature templates on evade mode enter - prevent visual lost
|
||||
public override void EnterEvadeMode(EvadeReason why)
|
||||
{
|
||||
if (me.IsInEvadeMode() || !me.IsAlive())
|
||||
return;
|
||||
|
||||
Unit owner = me.GetCharmerOrOwner();
|
||||
|
||||
me.CombatStop(true);
|
||||
if (owner != null && !me.HasUnitState(UnitState.Follow))
|
||||
{
|
||||
if (me.IsInEvadeMode() || !me.IsAlive())
|
||||
return;
|
||||
|
||||
Unit owner = me.GetCharmerOrOwner();
|
||||
|
||||
me.CombatStop(true);
|
||||
if (owner && !me.HasUnitState(UnitState.Follow))
|
||||
{
|
||||
me.GetMotionMaster().Clear();
|
||||
me.GetMotionMaster().MoveFollow(owner, SharedConst.PetFollowDist, me.GetFollowAngle());
|
||||
}
|
||||
me.GetMotionMaster().Clear();
|
||||
me.GetMotionMaster().MoveFollow(owner, SharedConst.PetFollowDist, me.GetFollowAngle());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
|
||||
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
|
||||
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Framework.Constants;
|
||||
@@ -6,50 +6,70 @@ using Game.AI;
|
||||
using Game.Entities;
|
||||
using Game.Scripting;
|
||||
|
||||
namespace Scripts.Pets
|
||||
namespace Scripts.Pets.Priest
|
||||
{
|
||||
namespace Priest
|
||||
[Script] // 198236 - Divine Image
|
||||
class npc_pet_pri_divine_image : PassiveAI
|
||||
{
|
||||
struct SpellIds
|
||||
const uint SpellPriestDivineImageSpellCheck = 405216;
|
||||
const uint SpellPriestInvokeTheNaaru = 196687;
|
||||
|
||||
public npc_pet_pri_divine_image(Creature creature) : base(creature) { }
|
||||
|
||||
public override void IsSummonedBy(WorldObject summoner)
|
||||
{
|
||||
public const uint GlyphOfShadowFiend = 58228;
|
||||
public const uint ShadowFiendDeath = 57989;
|
||||
public const uint LightWellCharges = 59907;
|
||||
me.CastSpell(me, SpellPriestInvokeTheNaaru);
|
||||
|
||||
if (me.ToTempSummon().IsGuardian() && summoner.IsUnit())
|
||||
(me as Guardian).SetBonusDamage((int)summoner.ToUnit().SpellBaseHealingBonusDone(SpellSchoolMask.Holy));
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_pet_pri_lightwell : PassiveAI
|
||||
public override void OnDespawn()
|
||||
{
|
||||
public npc_pet_pri_lightwell(Creature creature) : base(creature)
|
||||
{
|
||||
DoCast(creature, SpellIds.LightWellCharges, new Game.Spells.CastSpellExtraArgs(false));
|
||||
}
|
||||
|
||||
public override void EnterEvadeMode(EvadeReason why)
|
||||
{
|
||||
if (!me.IsAlive())
|
||||
return;
|
||||
|
||||
me.CombatStop(true);
|
||||
EngagementOver();
|
||||
me.ResetPlayerDamageReq();
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_pet_pri_shadowfiend : PetAI
|
||||
{
|
||||
public npc_pet_pri_shadowfiend(Creature creature) : base(creature) { }
|
||||
|
||||
public override void IsSummonedBy(WorldObject summoner)
|
||||
{
|
||||
Unit unitSummoner = summoner.ToUnit();
|
||||
if (unitSummoner == null)
|
||||
return;
|
||||
|
||||
if (unitSummoner.HasAura(SpellIds.GlyphOfShadowFiend))
|
||||
DoCastAOE(SpellIds.ShadowFiendDeath);
|
||||
}
|
||||
Unit owner = me.GetOwner();
|
||||
if (owner != null)
|
||||
owner.RemoveAura(SpellPriestDivineImageSpellCheck);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Script] // 189820 - Lightwell
|
||||
class npc_pet_pri_lightwell : PassiveAI
|
||||
{
|
||||
const uint SpellPriestLightwellCharges = 59907;
|
||||
|
||||
public npc_pet_pri_lightwell(Creature creature) : base(creature)
|
||||
{
|
||||
DoCast(me, SpellPriestLightwellCharges, false);
|
||||
}
|
||||
|
||||
public override void EnterEvadeMode(EvadeReason why)
|
||||
{
|
||||
if (!me.IsAlive())
|
||||
return;
|
||||
|
||||
me.CombatStop(true);
|
||||
EngagementOver();
|
||||
me.ResetPlayerDamageReq();
|
||||
}
|
||||
}
|
||||
|
||||
// 19668 - Shadowfiend
|
||||
[Script] // 62982 - Mindbender
|
||||
class npc_pet_pri_shadowfiend_mindbender : PetAI
|
||||
{
|
||||
const uint SpellPriestAtonement = 81749;
|
||||
const uint SpellPriestAtonementPassive = 195178;
|
||||
|
||||
public npc_pet_pri_shadowfiend_mindbender(Creature creature) : base(creature) { }
|
||||
|
||||
public override void IsSummonedBy(WorldObject summonerWO)
|
||||
{
|
||||
Unit summoner = summonerWO.ToUnit();
|
||||
if (summoner == null)
|
||||
return;
|
||||
|
||||
if (summoner.HasAura(SpellPriestAtonement))
|
||||
DoCastSelf(SpellPriestAtonementPassive, TriggerCastFlags.FullMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
|
||||
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
|
||||
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Framework.Constants;
|
||||
@@ -7,85 +7,74 @@ using Game.Entities;
|
||||
using Game.Scripting;
|
||||
using System;
|
||||
|
||||
namespace Scripts.Pets
|
||||
namespace Scripts.Pets.Shaman
|
||||
{
|
||||
namespace Shaman
|
||||
[Script]
|
||||
class npc_pet_shaman_earth_elemental : ScriptedAI
|
||||
{
|
||||
struct SpellIds
|
||||
{
|
||||
//npc_pet_shaman_earth_elemental
|
||||
public const uint AngeredEarth = 36213;
|
||||
const uint SpellShamanAngeredearth = 36213;
|
||||
|
||||
//npc_pet_shaman_fire_elemental
|
||||
public const uint FireBlast = 57984;
|
||||
public const uint FireNova = 12470;
|
||||
public const uint FireShield = 13376;
|
||||
public npc_pet_shaman_earth_elemental(Creature creature) : base(creature) { }
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(0), task =>
|
||||
{
|
||||
DoCastVictim(SpellShamanAngeredearth);
|
||||
task.Repeat(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(20));
|
||||
});
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_pet_shaman_earth_elemental : ScriptedAI
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
public npc_pet_shaman_earth_elemental(Creature creature) : base(creature) { }
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(0), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.AngeredEarth);
|
||||
task.Repeat(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(20));
|
||||
});
|
||||
}
|
||||
_scheduler.Update(diff);
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
public class npc_pet_shaman_fire_elemental : ScriptedAI
|
||||
{
|
||||
public npc_pet_shaman_fire_elemental(Creature creature) : base(creature) { }
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(20), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.FireNova);
|
||||
task.Repeat(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(20));
|
||||
});
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(20), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.FireShield);
|
||||
task.Repeat(TimeSpan.FromSeconds(2));
|
||||
});
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(0), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.FireBlast);
|
||||
task.Repeat(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(20));
|
||||
});
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_pet_shaman_fire_elemental : ScriptedAI
|
||||
{
|
||||
const uint SpellShamanFireblast = 57984;
|
||||
const uint SpellShamanFirenova = 12470;
|
||||
const uint SpellShamanFireshield = 13376;
|
||||
|
||||
public npc_pet_shaman_fire_elemental(Creature creature) : base(creature) { }
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(20), task =>
|
||||
{
|
||||
DoCastVictim(SpellShamanFirenova);
|
||||
task.Repeat(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(20));
|
||||
});
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(20), task =>
|
||||
{
|
||||
DoCastVictim(SpellShamanFireblast);
|
||||
task.Repeat(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(20));
|
||||
});
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(0), task =>
|
||||
{
|
||||
DoCastVictim(SpellShamanFireshield);
|
||||
task.Repeat(TimeSpan.FromSeconds(2));
|
||||
});
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff, DoMeleeAttackIfReady);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user