Core/Instances: Kill instance_encounters table, it is no longer neccessary
Port From (https://github.com/TrinityCore/TrinityCore/commit/47fc3cb852324119e81c01015b7cc4f39d43e559)
This commit is contained in:
@@ -543,7 +543,7 @@ namespace Framework.Constants
|
|||||||
Unused25 = 0x2000000,
|
Unused25 = 0x2000000,
|
||||||
Unused26 = 0x4000000,
|
Unused26 = 0x4000000,
|
||||||
Unused27 = 0x8000000,
|
Unused27 = 0x8000000,
|
||||||
DungeonBoss = 0x10000000, // Creature Is A Dungeon Boss (Set Dynamically, Do Not Add In Db)
|
DungeonBoss = 0x10000000, // Creature Is A Dungeon Boss
|
||||||
IgnorePathfinding = 0x20000000, // creature ignore pathfinding
|
IgnorePathfinding = 0x20000000, // creature ignore pathfinding
|
||||||
ImmunityKnockback = 0x40000000, // creature is immune to knockback effects
|
ImmunityKnockback = 0x40000000, // creature is immune to knockback effects
|
||||||
Unused31 = 0x80000000,
|
Unused31 = 0x80000000,
|
||||||
|
|||||||
@@ -151,12 +151,6 @@ namespace Framework.Constants
|
|||||||
ToBeDecided = 5
|
ToBeDecided = 5
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum EncounterCreditType
|
|
||||||
{
|
|
||||||
KillCreature = 0,
|
|
||||||
CastSpell = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum DoorType
|
public enum DoorType
|
||||||
{
|
{
|
||||||
Room = 0, // Door can open if encounter is not in progress
|
Room = 0, // Door can open if encounter is not in progress
|
||||||
|
|||||||
@@ -41,8 +41,6 @@ namespace Game.Chat.Commands
|
|||||||
foreach (var pair in Global.ObjectMgr.GetCreatureTemplates())
|
foreach (var pair in Global.ObjectMgr.GetCreatureTemplates())
|
||||||
{
|
{
|
||||||
CreatureTemplate data = pair.Value;
|
CreatureTemplate data = pair.Value;
|
||||||
if (!data.FlagsExtra.HasFlag(CreatureFlagsExtra.DungeonBoss))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
uint count = 0;
|
uint count = 0;
|
||||||
string scriptName = Global.ObjectMgr.GetScriptName(data.ScriptID);
|
string scriptName = Global.ObjectMgr.GetScriptName(data.ScriptID);
|
||||||
|
|||||||
@@ -1335,6 +1335,35 @@ namespace Game.DungeonFinding
|
|||||||
Log.outDebug(LogFilter.Lfg, "TeleportPlayer: Player {0} is being teleported in to map {1} (x: {2}, y: {3}, z: {4}) Result: {5}", player.GetName(), dungeon.map, dungeon.x, dungeon.y, dungeon.z, error);
|
Log.outDebug(LogFilter.Lfg, "TeleportPlayer: Player {0} is being teleported in to map {1} (x: {2}, y: {3}, z: {4}) Result: {5}", player.GetName(), dungeon.map, dungeon.x, dungeon.y, dungeon.z, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if dungeon can be rewarded, if any.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="gguid">Group guid</param>
|
||||||
|
/// <param name="dungeonEncounterIds">DungeonEncounter that was just completed</param>
|
||||||
|
/// <param name="currMap">Map of the instance where encounter was completed</param>
|
||||||
|
public void OnDungeonEncounterDone(ObjectGuid gguid, uint[] dungeonEncounterIds, Map currMap)
|
||||||
|
{
|
||||||
|
if (GetState(gguid) == LfgState.FinishedDungeon) // Shouldn't happen. Do not reward multiple times
|
||||||
|
{
|
||||||
|
Log.outDebug(LogFilter.Lfg, $"Group: {gguid} already rewarded");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint gDungeonId = GetDungeon(gguid);
|
||||||
|
LFGDungeonData dungeonDone = GetLFGDungeon(gDungeonId);
|
||||||
|
// LFGDungeons can point to a DungeonEncounter from any difficulty so we need this kind of lenient check
|
||||||
|
if (!dungeonEncounterIds.Contains(dungeonDone.finalDungeonEncounterId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
FinishDungeon(gguid, gDungeonId, currMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finish a dungeon and give reward, if any.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="gguid">Group guid</param>
|
||||||
|
/// <param name="dungeonId">Dungeonid</param>
|
||||||
|
/// <param name="currMap">Map of the instance where encounter was completed</param>
|
||||||
public void FinishDungeon(ObjectGuid gguid, uint dungeonId, Map currMap)
|
public void FinishDungeon(ObjectGuid gguid, uint dungeonId, Map currMap)
|
||||||
{
|
{
|
||||||
uint gDungeonId = GetDungeon(gguid);
|
uint gDungeonId = GetDungeon(gguid);
|
||||||
@@ -2289,6 +2318,10 @@ namespace Game.DungeonFinding
|
|||||||
contentTuningId = dbc.ContentTuningID;
|
contentTuningId = dbc.ContentTuningID;
|
||||||
difficulty = dbc.DifficultyID;
|
difficulty = dbc.DifficultyID;
|
||||||
seasonal = dbc.Flags[0].HasAnyFlag(LfgFlags.Seasonal);
|
seasonal = dbc.Flags[0].HasAnyFlag(LfgFlags.Seasonal);
|
||||||
|
|
||||||
|
var journalEncounter = CliDB.JournalEncounterStorage.LookupByKey(dbc.FinalEncounterID);
|
||||||
|
if (journalEncounter != null)
|
||||||
|
finalDungeonEncounterId = journalEncounter.DungeonEncounterID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint id;
|
public uint id;
|
||||||
@@ -2302,6 +2335,7 @@ namespace Game.DungeonFinding
|
|||||||
public bool seasonal;
|
public bool seasonal;
|
||||||
public float x, y, z, o;
|
public float x, y, z, o;
|
||||||
public ushort requiredItemLevel;
|
public ushort requiredItemLevel;
|
||||||
|
public uint finalDungeonEncounterId;
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
public uint Entry() { return (uint)(id + ((int)type << 24)); }
|
public uint Entry() { return (uint)(id + ((int)type << 24)); }
|
||||||
|
|||||||
@@ -84,13 +84,6 @@ namespace Game.Entities
|
|||||||
Creature victim = _victim.ToCreature();
|
Creature victim = _victim.ToCreature();
|
||||||
if (victim != null)
|
if (victim != null)
|
||||||
{
|
{
|
||||||
if (victim.IsDungeonBoss())
|
|
||||||
{
|
|
||||||
InstanceScript instance = _victim.GetInstanceScript();
|
|
||||||
if (instance != null)
|
|
||||||
instance.UpdateEncounterStateForKilledCreature(_victim.GetEntry(), _victim);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_killers.Empty())
|
if (!_killers.Empty())
|
||||||
{
|
{
|
||||||
uint guildId = victim.GetMap().GetOwnerGuildId();
|
uint guildId = victim.GetMap().GetOwnerGuildId();
|
||||||
|
|||||||
@@ -5495,97 +5495,6 @@ namespace Game
|
|||||||
|
|
||||||
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} access requirement definitions in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
|
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} access requirement definitions in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
|
||||||
}
|
}
|
||||||
public void LoadInstanceEncounters()
|
|
||||||
{
|
|
||||||
uint oldMSTime = Time.GetMSTime();
|
|
||||||
|
|
||||||
// 0 1 2 3
|
|
||||||
SQLResult result = DB.World.Query("SELECT entry, creditType, creditEntry, lastEncounterDungeon FROM instance_encounters");
|
|
||||||
if (result.IsEmpty())
|
|
||||||
{
|
|
||||||
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 instance encounters, table is empty!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint count = 0;
|
|
||||||
Dictionary<uint, Tuple<uint, DungeonEncounterRecord>> dungeonLastBosses = new();
|
|
||||||
do
|
|
||||||
{
|
|
||||||
uint entry = result.Read<uint>(0);
|
|
||||||
EncounterCreditType creditType = (EncounterCreditType)result.Read<byte>(1);
|
|
||||||
uint creditEntry = result.Read<uint>(2);
|
|
||||||
uint lastEncounterDungeon = result.Read<uint>(3);
|
|
||||||
DungeonEncounterRecord dungeonEncounter = CliDB.DungeonEncounterStorage.LookupByKey(entry);
|
|
||||||
if (dungeonEncounter == null)
|
|
||||||
{
|
|
||||||
Log.outError(LogFilter.Sql, "Table `instance_encounters` has an invalid encounter id {0}, skipped!", entry);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lastEncounterDungeon != 0 && Global.LFGMgr.GetLFGDungeonEntry(lastEncounterDungeon) == 0)
|
|
||||||
{
|
|
||||||
Log.outError(LogFilter.Sql, "Table `instance_encounters` has an encounter {0} ({1}) marked as final for invalid dungeon id {2}, skipped!",
|
|
||||||
entry, dungeonEncounter.Name[Global.WorldMgr.GetDefaultDbcLocale()], lastEncounterDungeon);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var pair = dungeonLastBosses.LookupByKey(lastEncounterDungeon);
|
|
||||||
if (lastEncounterDungeon != 0)
|
|
||||||
{
|
|
||||||
if (pair != null)
|
|
||||||
{
|
|
||||||
Log.outError(LogFilter.Sql, "Table `instance_encounters` specified encounter {0} ({1}) as last encounter but {2} ({3}) is already marked as one, skipped!",
|
|
||||||
entry, dungeonEncounter.Name[Global.WorldMgr.GetDefaultDbcLocale()], pair.Item1, pair.Item2.Name[Global.WorldMgr.GetDefaultDbcLocale()]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
dungeonLastBosses[lastEncounterDungeon] = Tuple.Create(entry, dungeonEncounter);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (creditType)
|
|
||||||
{
|
|
||||||
case EncounterCreditType.KillCreature:
|
|
||||||
{
|
|
||||||
CreatureTemplate creatureInfo = GetCreatureTemplate(creditEntry);
|
|
||||||
if (creatureInfo == null)
|
|
||||||
{
|
|
||||||
Log.outError(LogFilter.Sql, "Table `instance_encounters` has an invalid creature (entry {0}) linked to the encounter {1} ({2}), skipped!",
|
|
||||||
creditEntry, entry, dungeonEncounter.Name[Global.WorldMgr.GetDefaultDbcLocale()]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
creatureInfo.FlagsExtra |= CreatureFlagsExtra.DungeonBoss;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case EncounterCreditType.CastSpell:
|
|
||||||
if (!Global.SpellMgr.HasSpellInfo(creditEntry, Difficulty.None))
|
|
||||||
{
|
|
||||||
Log.outError(LogFilter.Sql, "Table `instance_encounters` has an invalid spell (entry {0}) linked to the encounter {1} ({2}), skipped!",
|
|
||||||
creditEntry, entry, dungeonEncounter.Name[Global.WorldMgr.GetDefaultDbcLocale()]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Log.outError(LogFilter.Sql, "Table `instance_encounters` has an invalid credit type ({0}) for encounter {1} ({2}), skipped!",
|
|
||||||
creditType, entry, dungeonEncounter.Name[Global.WorldMgr.GetDefaultDbcLocale()]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dungeonEncounter.DifficultyID == 0)
|
|
||||||
{
|
|
||||||
foreach (var difficulty in CliDB.DifficultyStorage.Values)
|
|
||||||
{
|
|
||||||
if (Global.DB2Mgr.GetMapDifficultyData((uint)dungeonEncounter.MapID, (Difficulty)difficulty.Id) != null)
|
|
||||||
_dungeonEncounterStorage.Add(MathFunctions.MakePair64((uint)dungeonEncounter.MapID, difficulty.Id), new DungeonEncounter(dungeonEncounter, creditType, creditEntry, lastEncounterDungeon));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
_dungeonEncounterStorage.Add(MathFunctions.MakePair64((uint)dungeonEncounter.MapID, (uint)dungeonEncounter.DifficultyID), new DungeonEncounter(dungeonEncounter, creditType, creditEntry, lastEncounterDungeon));
|
|
||||||
|
|
||||||
++count;
|
|
||||||
} while (result.NextRow());
|
|
||||||
|
|
||||||
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} instance encounters in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
|
|
||||||
}
|
|
||||||
public void LoadSpawnGroupTemplates()
|
public void LoadSpawnGroupTemplates()
|
||||||
{
|
{
|
||||||
uint oldMSTime = Time.GetMSTime();
|
uint oldMSTime = Time.GetMSTime();
|
||||||
@@ -5876,10 +5785,6 @@ namespace Game
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
public List<DungeonEncounter> GetDungeonEncounterList(uint mapId, Difficulty difficulty)
|
|
||||||
{
|
|
||||||
return _dungeonEncounterStorage.LookupByKey(MathFunctions.MakePair64(mapId, (uint)difficulty));
|
|
||||||
}
|
|
||||||
public bool IsTransportMap(uint mapId) { return _transportMaps.Contains((ushort)mapId); }
|
public bool IsTransportMap(uint mapId) { return _transportMaps.Contains((ushort)mapId); }
|
||||||
public SpawnGroupTemplateData GetSpawnGroupData(uint groupId) { return _spawnGroupDataStorage.LookupByKey(groupId); }
|
public SpawnGroupTemplateData GetSpawnGroupData(uint groupId) { return _spawnGroupDataStorage.LookupByKey(groupId); }
|
||||||
public SpawnGroupTemplateData GetSpawnGroupData(SpawnObjectType type, ulong spawnId)
|
public SpawnGroupTemplateData GetSpawnGroupData(SpawnObjectType type, ulong spawnId)
|
||||||
@@ -10992,7 +10897,6 @@ namespace Game
|
|||||||
List<uint> _tavernAreaTriggerStorage = new();
|
List<uint> _tavernAreaTriggerStorage = new();
|
||||||
Dictionary<uint, AreaTriggerStruct> _areaTriggerStorage = new();
|
Dictionary<uint, AreaTriggerStruct> _areaTriggerStorage = new();
|
||||||
Dictionary<ulong, AccessRequirement> _accessRequirementStorage = new();
|
Dictionary<ulong, AccessRequirement> _accessRequirementStorage = new();
|
||||||
MultiMap<ulong, DungeonEncounter> _dungeonEncounterStorage = new();
|
|
||||||
Dictionary<uint, WorldSafeLocsEntry> _worldSafeLocs = new();
|
Dictionary<uint, WorldSafeLocsEntry> _worldSafeLocs = new();
|
||||||
|
|
||||||
Dictionary<HighGuid, ObjectGuidGenerator> _guidGenerators = new();
|
Dictionary<HighGuid, ObjectGuidGenerator> _guidGenerators = new();
|
||||||
@@ -11530,22 +11434,6 @@ namespace Game
|
|||||||
public uint PortLocId;
|
public uint PortLocId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DungeonEncounter
|
|
||||||
{
|
|
||||||
public DungeonEncounter(DungeonEncounterRecord _dbcEntry, EncounterCreditType _creditType, uint _creditEntry, uint _lastEncounterDungeon)
|
|
||||||
{
|
|
||||||
dbcEntry = _dbcEntry;
|
|
||||||
creditType = _creditType;
|
|
||||||
creditEntry = _creditEntry;
|
|
||||||
lastEncounterDungeon = _lastEncounterDungeon;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DungeonEncounterRecord dbcEntry;
|
|
||||||
public EncounterCreditType creditType;
|
|
||||||
public uint creditEntry;
|
|
||||||
public uint lastEncounterDungeon;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class MailLevelReward
|
public class MailLevelReward
|
||||||
{
|
{
|
||||||
public MailLevelReward(RaceMask<ulong> _raceMask, uint _mailTemplateId = 0, uint _senderEntry = 0)
|
public MailLevelReward(RaceMask<ulong> _raceMask, uint _mailTemplateId = 0, uint _senderEntry = 0)
|
||||||
|
|||||||
@@ -385,6 +385,8 @@ namespace Game.Maps
|
|||||||
SendBossKillCredit(dungeonEncounter.Id);
|
SendBossKillCredit(dungeonEncounter.Id);
|
||||||
if (dungeonEncounter.CompleteWorldStateID != 0)
|
if (dungeonEncounter.CompleteWorldStateID != 0)
|
||||||
DoUpdateWorldState((uint)dungeonEncounter.CompleteWorldStateID, 1);
|
DoUpdateWorldState((uint)dungeonEncounter.CompleteWorldStateID, 1);
|
||||||
|
|
||||||
|
UpdateLfgEncounterState(bossInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.DoOnPlayers(player => player.AtEndOfEncounter(EncounterType.DungeonEncounter));
|
instance.DoOnPlayers(player => player.AtEndOfEncounter(EncounterType.DungeonEncounter));
|
||||||
@@ -796,53 +798,18 @@ namespace Game.Maps
|
|||||||
instance.SendToPlayers(bossKillCreditMessage);
|
instance.SendToPlayers(bossKillCreditMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateEncounterStateForKilledCreature(uint creatureId, Unit source)
|
void UpdateLfgEncounterState(BossInfo bossInfo)
|
||||||
{
|
{
|
||||||
UpdateEncounterState(EncounterCreditType.KillCreature, creatureId, source);
|
foreach (var player in instance.GetPlayers())
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateEncounterStateForSpellCast(uint spellId, Unit source)
|
|
||||||
{
|
|
||||||
UpdateEncounterState(EncounterCreditType.CastSpell, spellId, source);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateEncounterState(EncounterCreditType type, uint creditEntry, Unit source)
|
|
||||||
{
|
|
||||||
var encounters = Global.ObjectMgr.GetDungeonEncounterList(instance.GetId(), instance.GetDifficultyID());
|
|
||||||
if (encounters.Empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
uint dungeonId = 0;
|
|
||||||
|
|
||||||
foreach (var encounter in encounters)
|
|
||||||
{
|
{
|
||||||
if (encounter.creditType == type && encounter.creditEntry == creditEntry)
|
if (player != null)
|
||||||
{
|
|
||||||
if (encounter.dbcEntry.CompleteWorldStateID != 0)
|
|
||||||
DoUpdateWorldState((uint)encounter.dbcEntry.CompleteWorldStateID, 1);
|
|
||||||
|
|
||||||
if (encounter.lastEncounterDungeon != 0)
|
|
||||||
{
|
|
||||||
dungeonId = encounter.lastEncounterDungeon;
|
|
||||||
Log.outDebug(LogFilter.Lfg, "UpdateEncounterState: Instance {0} (instanceId {1}) completed encounter {2}. Credit Dungeon: {3}",
|
|
||||||
instance.GetMapName(), instance.GetInstanceId(), encounter.dbcEntry.Name[Global.WorldMgr.GetDefaultDbcLocale()], dungeonId);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dungeonId != 0)
|
|
||||||
{
|
|
||||||
var players = instance.GetPlayers();
|
|
||||||
foreach (var player in players)
|
|
||||||
{
|
{
|
||||||
Group grp = player.GetGroup();
|
Group grp = player.GetGroup();
|
||||||
if (grp != null)
|
if (grp != null && grp.IsLFGGroup())
|
||||||
if (grp.IsLFGGroup())
|
{
|
||||||
{
|
Global.LFGMgr.OnDungeonEncounterDone(grp.GetGUID(), bossInfo.DungeonEncounters.Select(entry => entry.Id).ToArray(), instance);
|
||||||
Global.LFGMgr.FinishDungeon(grp.GetGUID(), dungeonId, instance);
|
break;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -743,9 +743,6 @@ namespace Game
|
|||||||
Log.outInfo(LogFilter.ServerLoading, "Loading LFG entrance positions..."); // Must be after areatriggers
|
Log.outInfo(LogFilter.ServerLoading, "Loading LFG entrance positions..."); // Must be after areatriggers
|
||||||
Global.LFGMgr.LoadLFGDungeons();
|
Global.LFGMgr.LoadLFGDungeons();
|
||||||
|
|
||||||
Log.outInfo(LogFilter.ServerLoading, "Loading Dungeon boss data...");
|
|
||||||
Global.ObjectMgr.LoadInstanceEncounters();
|
|
||||||
|
|
||||||
Log.outInfo(LogFilter.ServerLoading, "Loading LFG rewards...");
|
Log.outInfo(LogFilter.ServerLoading, "Loading LFG rewards...");
|
||||||
Global.LFGMgr.LoadRewards();
|
Global.LFGMgr.LoadRewards();
|
||||||
|
|
||||||
|
|||||||
@@ -1339,35 +1339,6 @@ namespace Scripts.Spells.Generic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Script]
|
|
||||||
class spell_gen_dungeon_credit : SpellScript
|
|
||||||
{
|
|
||||||
public override bool Load()
|
|
||||||
{
|
|
||||||
return GetCaster().GetTypeId() == TypeId.Unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CreditEncounter()
|
|
||||||
{
|
|
||||||
// This hook is executed for every target, make sure we only credit instance once
|
|
||||||
if (_handled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_handled = true;
|
|
||||||
Unit caster = GetCaster();
|
|
||||||
InstanceScript instance = caster.GetInstanceScript();
|
|
||||||
if (instance != null)
|
|
||||||
instance.UpdateEncounterStateForSpellCast(GetSpellInfo().Id, caster);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Register()
|
|
||||||
{
|
|
||||||
AfterHit.Add(new(CreditEncounter));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _handled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Script] // 50051 - Ethereal Pet Aura
|
[Script] // 50051 - Ethereal Pet Aura
|
||||||
class spell_ethereal_pet_AuraScript : AuraScript
|
class spell_ethereal_pet_AuraScript : AuraScript
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user