diff --git a/Modules/WDE.HttpDatabase/Models/MySqlLootEntry.cs b/Modules/WDE.HttpDatabase/Models/MySqlLootEntry.cs index 9970eee65..932acbc24 100644 --- a/Modules/WDE.HttpDatabase/Models/MySqlLootEntry.cs +++ b/Modules/WDE.HttpDatabase/Models/MySqlLootEntry.cs @@ -6,6 +6,7 @@ namespace WDE.HttpDatabase.Models; public class JsonLootEntry : ILootEntry { public LootSourceType SourceType { get; set; } + public LootType LootType { get; set; } public uint Entry { get; set; } public int ItemOrCurrencyId { get; set; } public uint Reference { get; set; } diff --git a/Modules/WDE.LootEditor/Editor/Standalone/StandaloneLootEditorToolBar.axaml b/Modules/WDE.LootEditor/Editor/Standalone/StandaloneLootEditorToolBar.axaml index f655dc199..0b0ff164e 100644 --- a/Modules/WDE.LootEditor/Editor/Standalone/StandaloneLootEditorToolBar.axaml +++ b/Modules/WDE.LootEditor/Editor/Standalone/StandaloneLootEditorToolBar.axaml @@ -22,7 +22,7 @@ + Items="{CompiledBinding SupportedLootTypes}" /> diff --git a/Modules/WDE.LootEditor/Editor/Standalone/StandaloneLootEditorViewModel.cs b/Modules/WDE.LootEditor/Editor/Standalone/StandaloneLootEditorViewModel.cs index 36cf6a7e7..bc845091e 100644 --- a/Modules/WDE.LootEditor/Editor/Standalone/StandaloneLootEditorViewModel.cs +++ b/Modules/WDE.LootEditor/Editor/Standalone/StandaloneLootEditorViewModel.cs @@ -58,6 +58,8 @@ public LootSourceType LootType } } + public IReadOnlyList SupportedLootTypes { get; } + [Notify] private bool canChangeLootType = true; [Notify] private bool canChangeEntry = true; [Notify] private uint solutionEntry; @@ -192,6 +194,7 @@ public StandaloneLootEditorViewModel( ITextDocumentService textDocumentService, IParameterFactory parameterFactory, ICurrentCoreVersion currentCoreVersion, + ILootEditorFeatures lootEditorFeatures, PerDatabaseTableLootSolutionItem? solutionItem = null ) { @@ -202,6 +205,7 @@ public StandaloneLootEditorViewModel( this.parameterPickerService = parameterPickerService; this.messageBoxService = messageBoxService; this.currentCoreVersion = currentCoreVersion; + SupportedLootTypes = lootEditorFeatures.SupportedTypes; legacyDifficulties[0] = DifficultyViewModel.Legacy(0, "default"); legacyDifficulties[1] = DifficultyViewModel.Legacy(1, "heroic dung/25 raid"); legacyDifficulties[2] = DifficultyViewModel.Legacy(2, "10 heroic raid"); diff --git a/Modules/WDE.LootEditor/Editor/ViewModels/LootEditorViewModel.cs b/Modules/WDE.LootEditor/Editor/ViewModels/LootEditorViewModel.cs index 7ce180b41..6343dbeb1 100644 --- a/Modules/WDE.LootEditor/Editor/ViewModels/LootEditorViewModel.cs +++ b/Modules/WDE.LootEditor/Editor/ViewModels/LootEditorViewModel.cs @@ -1086,7 +1086,7 @@ private async Task UnloadLoot(LootSourceType type, LootEntry menu) private IReadOnlyList Roots => (LootEditingMode == LootEditingMode.PerDatabaseTable) ? PerDatabaseSolutionItems : - Loots.Where(x => x.LootSourceType != LootSourceType.Reference || (uint)x.LootEntry == perEntitySolutionItem!.Entry) + Loots.Where(x => x.LootSourceType != LootSourceType.Reference || perEntitySolutionItem!.Type == LootSourceType.Reference && (uint)x.LootEntry == perEntitySolutionItem!.Entry) .Select(x => x.LootEntry) .ToList(); @@ -1128,7 +1128,7 @@ private bool VerifyDuplicateKeys() { var loot = lootGroup.LootItems[lootIndex]; loot.IsDuplicate = false; - var item = loot.ItemOrCurrencyId.Value; + var item = loot.IsReference ? loot.ReferenceEntry : loot.ItemOrCurrencyId.Value; var minPatch = loot.MinPatch.Value; if (!keys.Add((item, minPatch))) { diff --git a/Modules/WDE.LootEditor/Editor/ViewModels/LootItemViewModel.cs b/Modules/WDE.LootEditor/Editor/ViewModels/LootItemViewModel.cs index 90276628f..04313f53e 100644 --- a/Modules/WDE.LootEditor/Editor/ViewModels/LootItemViewModel.cs +++ b/Modules/WDE.LootEditor/Editor/ViewModels/LootItemViewModel.cs @@ -249,6 +249,7 @@ public LootModel ToModel() SourceType = Parent.LootSourceType, Entry = (uint)Parent.LootEntry, ItemOrCurrencyId = (int)ItemOrCurrencyId.Value, + LootType = IsReference ? LootType.Reference : LootType.Item, Chance = Math.Abs(Chance.Value), QuestRequired = Chance.Value < 0, LootMode = (uint)LootMode.Value, diff --git a/Modules/WDE.LootEditor/QueryGenerator/CmangosLootQueryGenerator.cs b/Modules/WDE.LootEditor/QueryGenerator/CmangosLootQueryGenerator.cs index 6a395e946..ec8aa5198 100644 --- a/Modules/WDE.LootEditor/QueryGenerator/CmangosLootQueryGenerator.cs +++ b/Modules/WDE.LootEditor/QueryGenerator/CmangosLootQueryGenerator.cs @@ -64,7 +64,7 @@ public IQuery GenerateQuery(IReadOnlyList models) .BulkInsert(group.Items.Select(x => new { entry = x.Loot.Entry, - item = x.Loot.ItemOrCurrencyId, + item = x.Loot.IsReference() && x.Loot.ItemOrCurrencyId == 0 ? (long)x.Loot.Reference : x.Loot.ItemOrCurrencyId, ChanceOrQuestChance = (x.Loot.QuestRequired ? -1 : 1) * x.Loot.Chance, groupid = x.Loot.GroupId, mincountOrRef = x.Loot.IsReference() ? -(int)x.Loot.Reference : x.Loot.MinCount, diff --git a/Modules/WDE.LootEditor/QueryGenerator/TrinityLootQueryGenerator.cs b/Modules/WDE.LootEditor/QueryGenerator/TrinityLootQueryGenerator.cs index 76c761f42..708073a7a 100644 --- a/Modules/WDE.LootEditor/QueryGenerator/TrinityLootQueryGenerator.cs +++ b/Modules/WDE.LootEditor/QueryGenerator/TrinityLootQueryGenerator.cs @@ -129,7 +129,7 @@ public IQuery GenerateUpdateLootIds(LootSourceType sourceType, uint solutionEntr } } -[RequiresCore("TrinityMaster", "TrinityWrath", "Azeroth")] +[RequiresCore("TrinityWrath", "Azeroth")] [AutoRegister] [SingleInstance] public class TrinityLootQueryGenerator : BaseTrinityLootQueryGenerator @@ -143,7 +143,7 @@ protected override object CreateDatabaseObjectRow(LootModel x) return new { Entry = x.Loot.Entry, - Item = x.Loot.ItemOrCurrencyId, + Item = x.Loot.IsReference() && x.Loot.ItemOrCurrencyId == 0 ? (long)x.Loot.Reference : x.Loot.ItemOrCurrencyId, Reference = x.Loot.Reference, Chance = x.Loot.Chance, QuestRequired = x.Loot.QuestRequired, @@ -156,6 +156,33 @@ protected override object CreateDatabaseObjectRow(LootModel x) } } +[RequiresCore("TrinityMaster")] +[AutoRegister] +[SingleInstance] +public class TrinityMasterLootQueryGenerator : BaseTrinityLootQueryGenerator +{ + public TrinityMasterLootQueryGenerator(IConditionQueryGenerator conditionQueryGenerator, ICurrentCoreVersion currentCoreVersion, ILootEditorFeatures editorFeatures) : base(conditionQueryGenerator, currentCoreVersion, editorFeatures) + { + } + + protected override object CreateDatabaseObjectRow(LootModel x) + { + return new + { + Entry = x.Loot.Entry, + Item = x.Loot.LootType == LootType.Reference ? x.Loot.Reference : (long)x.Loot.ItemOrCurrencyId, + ItemType = (int)x.Loot.LootType, + Chance = x.Loot.Chance, + QuestRequired = x.Loot.QuestRequired, + LootMode = x.Loot.LootMode, + GroupId = x.Loot.GroupId, + MinCount = x.Loot.MinCount, + MaxCount = x.Loot.MaxCount, + Comment = x.Loot.Comment + }; + } +} + [RequiresCore("TrinityCata")] [AutoRegister] [SingleInstance] @@ -170,7 +197,7 @@ protected override object CreateDatabaseObjectRow(LootModel x) return new { Entry = x.Loot.Entry, - Item = Math.Abs(x.Loot.ItemOrCurrencyId), + Item = x.Loot.IsReference() && x.Loot.ItemOrCurrencyId == 0 ? (long)x.Loot.Reference : Math.Abs(x.Loot.ItemOrCurrencyId), IsCurrency = x.Loot.ItemOrCurrencyId < 0, Reference = x.Loot.Reference, Chance = x.Loot.Chance, diff --git a/WoWDatabaseEditor.Common/WDE.CMMySqlDatabase/Models/Loot.cs b/WoWDatabaseEditor.Common/WDE.CMMySqlDatabase/Models/Loot.cs index b7c570cf4..24ed85f20 100644 --- a/WoWDatabaseEditor.Common/WDE.CMMySqlDatabase/Models/Loot.cs +++ b/WoWDatabaseEditor.Common/WDE.CMMySqlDatabase/Models/Loot.cs @@ -6,7 +6,9 @@ namespace WDE.CMMySqlDatabase.Models; public abstract class BaseLootTemplate : ILootEntry { public abstract LootSourceType SourceType { get; } - + + public LootType LootType => Reference != 0 ? LootType.Reference : LootType.Item; + [PrimaryKey] [Column(Name = "entry")] public uint Entry { get; set; } diff --git a/WoWDatabaseEditor.Common/WDE.Common/Database/LootType.cs b/WoWDatabaseEditor.Common/WDE.Common/Database/LootType.cs deleted file mode 100644 index 2565cea7f..000000000 --- a/WoWDatabaseEditor.Common/WDE.Common/Database/LootType.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace WDE.Common.Database; - -public enum LootType -{ - -} \ No newline at end of file diff --git a/WoWDatabaseEditor.Common/WDE.Common/Utils/AsyncAutoCommand.cs b/WoWDatabaseEditor.Common/WDE.Common/Utils/AsyncAutoCommand.cs index 859d4a84a..5f877c09e 100644 --- a/WoWDatabaseEditor.Common/WDE.Common/Utils/AsyncAutoCommand.cs +++ b/WoWDatabaseEditor.Common/WDE.Common/Utils/AsyncAutoCommand.cs @@ -7,6 +7,7 @@ using Prism.Commands; using WDE.Common.Annotations; using WDE.Common.Exceptions; +using WDE.Common.Services; using WDE.Common.Services.MessageBox; using WDE.Common.Tasks; @@ -46,7 +47,14 @@ public AsyncAutoCommand(Func execute, { LOG.LogError(e, "Error in {0} at {1}:{2}", caller, callerFile, callerLineNumber); } - onException?.Invoke(e); + if (onException == null) + { + var service = DI.Resolve(); + if (service != null) + GlobalApplication.MainThread.Dispatch(() => CommandExtensions.ShowError(service, e, null)); + } + else + onException?.Invoke(e); }, continueOnCapturedContext); } @@ -116,7 +124,14 @@ public AsyncAutoCommand([NotNull] e => { IsBusy = false; - onException?.Invoke(e); + if (onException == null) + { + var service = DI.Resolve(); + if (service != null) + GlobalApplication.MainThread.Dispatch(() => CommandExtensions.ShowError(service, e, null)); + } + else + onException?.Invoke(e); }, continueOnCapturedContext); } @@ -290,7 +305,7 @@ public static IAsyncCommand WrapMessageBox(this IAsyncCommand cmd, I }); } - private static async Task ShowError(IMessageBoxService messageBoxService, Exception e, string? header, + internal static async Task ShowError(IMessageBoxService messageBoxService, Exception e, string? header, [CallerMemberName] string? caller = null, [CallerFilePath] string? callerFile = null, [CallerLineNumber] int? callerLineNumber = null) diff --git a/WoWDatabaseEditor.Common/WDE.TrinityMySqlDatabase/Database/TrinityMasterMySqlDatabaseProvider.cs b/WoWDatabaseEditor.Common/WDE.TrinityMySqlDatabase/Database/TrinityMasterMySqlDatabaseProvider.cs index 68cdba530..5201a5205 100644 --- a/WoWDatabaseEditor.Common/WDE.TrinityMySqlDatabase/Database/TrinityMasterMySqlDatabaseProvider.cs +++ b/WoWDatabaseEditor.Common/WDE.TrinityMySqlDatabase/Database/TrinityMasterMySqlDatabaseProvider.cs @@ -320,8 +320,8 @@ public override async Task> GetCreatureTem public override async Task GetCreatureTemplateAddon(uint entry) { - await using var model = Database(); - return await model.CreatureTemplateAddon.FirstOrDefaultAsync(x => x.Entry == entry); + using var model = Database(); + return model.CreatureTemplateAddon.FirstOrDefault(x => x.Entry == entry); } public override async Task?> GetPlayerChoicesAsync() @@ -542,4 +542,132 @@ public override async Task> GetConversationAct await using var model = Database(); return await model.ConversationActor.OrderBy(x => x.ConversationId).ThenBy(x => x.Idx).ToListAsync(); } + + + public override async Task> GetLoot(LootSourceType type) + { + await using var database = Database(); + switch (type) + { + case LootSourceType.Item: + return await database.ItemMasterLootTemplate.OrderBy(x => x.Entry) + .ThenBy(x => x.GroupId) + .ThenBy(x => x.ItemOrCurrencyId) + .ToListAsync(); + case LootSourceType.GameObject: + return await database.GameObjectMasterLootTemplate.OrderBy(x => x.Entry) + .ThenBy(x => x.GroupId) + .ThenBy(x => x.ItemOrCurrencyId) + .ToListAsync(); + case LootSourceType.Fishing: + return await database.FishingMasterLootTemplate.OrderBy(x => x.Entry) + .ThenBy(x => x.GroupId) + .ThenBy(x => x.ItemOrCurrencyId) + .ToListAsync(); + case LootSourceType.Pickpocketing: + return await database.PickpocketingMasterLootTemplate.OrderBy(x => x.Entry) + .ThenBy(x => x.GroupId) + .ThenBy(x => x.ItemOrCurrencyId) + .ToListAsync(); + case LootSourceType.Skinning: + return await database.SkinningMasterLootTemplate.OrderBy(x => x.Entry) + .ThenBy(x => x.GroupId) + .ThenBy(x => x.ItemOrCurrencyId) + .ToListAsync(); + case LootSourceType.Disenchant: + return await database.DisenchantMasterLootTemplate.OrderBy(x => x.Entry) + .ThenBy(x => x.GroupId) + .ThenBy(x => x.ItemOrCurrencyId) + .ToListAsync(); + case LootSourceType.Prospecting: + return await database.ProspectingMasterLootTemplate.OrderBy(x => x.Entry) + .ThenBy(x => x.GroupId) + .ThenBy(x => x.ItemOrCurrencyId) + .ToListAsync(); + case LootSourceType.Milling: + return await database.MillingMasterLootTemplate.OrderBy(x => x.Entry) + .ThenBy(x => x.GroupId) + .ThenBy(x => x.ItemOrCurrencyId) + .ToListAsync(); + case LootSourceType.Reference: + return await database.ReferenceMasterLootTemplate.OrderBy(x => x.Entry) + .ThenBy(x => x.GroupId) + .ThenBy(x => x.ItemOrCurrencyId) + .ToListAsync(); + case LootSourceType.Creature: + return await database.CreatureMasterLootTemplate.OrderBy(x => x.Entry) + .ThenBy(x => x.GroupId) + .ThenBy(x => x.ItemOrCurrencyId) + .ToListAsync(); + case LootSourceType.Mail: + return await database.MailMasterLootTemplate.OrderBy(x => x.Entry) + .ThenBy(x => x.GroupId) + .ThenBy(x => x.ItemOrCurrencyId) + .ToListAsync(); + case LootSourceType.Spell: + return await database.SpellMasterLootTemplate.OrderBy(x => x.Entry) + .ThenBy(x => x.GroupId) + .ThenBy(x => x.ItemOrCurrencyId) + .ToListAsync(); + default: + throw new ArgumentOutOfRangeException(nameof(type), type, null); + } + } + + public override async Task> GetReferenceLootCrossReference(uint lootId) + { + if (lootId == 0) + return Array.Empty(); + await using var database = Database(); + var loot = new[] + { + await database.CreatureMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync(), + await database.GameObjectMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync(), + await database.ItemMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync(), + await database.FishingMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync(), + await database.PickpocketingMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync(), + await database.SkinningMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync(), + await database.DisenchantMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync(), + await database.ProspectingMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync(), + await database.MillingMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync(), + await database.MailMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync(), + await database.SpellMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync(), + await database.ReferenceLootTemplate.Where(x => x.Reference == lootId).ToListAsync(), + }; + return loot.SelectMany(x => x).ToList(); + } + + public override async Task> GetLoot(LootSourceType type, uint entry) + { + await using var database = Database(); + switch (type) + { + case LootSourceType.Item: + return await database.ItemMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync(); + case LootSourceType.GameObject: + return await database.GameObjectMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync(); + case LootSourceType.Fishing: + return await database.FishingMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync(); + case LootSourceType.Pickpocketing: + return await database.PickpocketingMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync(); + case LootSourceType.Skinning: + return await database.SkinningMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync(); + case LootSourceType.Disenchant: + return await database.DisenchantMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync(); + case LootSourceType.Prospecting: + return await database.ProspectingMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync(); + case LootSourceType.Milling: + return await database.MillingMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync(); + case LootSourceType.Reference: + return await database.ReferenceMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync(); + case LootSourceType.Creature: + return await database.CreatureMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync(); + case LootSourceType.Mail: + return await database.MailMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync(); + case LootSourceType.Spell: + return await database.SpellMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync(); + default: + throw new ArgumentOutOfRangeException(nameof(type), type, null); + } + } } \ No newline at end of file diff --git a/WoWDatabaseEditor.Common/WDE.TrinityMySqlDatabase/Models/Databases/TrinityMasterDatabase.cs b/WoWDatabaseEditor.Common/WDE.TrinityMySqlDatabase/Models/Databases/TrinityMasterDatabase.cs index 89db78f14..0724b1292 100644 --- a/WoWDatabaseEditor.Common/WDE.TrinityMySqlDatabase/Models/Databases/TrinityMasterDatabase.cs +++ b/WoWDatabaseEditor.Common/WDE.TrinityMySqlDatabase/Models/Databases/TrinityMasterDatabase.cs @@ -27,4 +27,17 @@ public class TrinityMasterDatabase : BaseTrinityDatabase public ITable WaypointData => this.GetTable(); public ITable ConditionsMaster => this.GetTable(); public ITable ConversationActor => this.GetTable(); + + public ITable ItemMasterLootTemplate => this.GetTable(); + public ITable PickpocketingMasterLootTemplate => this.GetTable(); + public ITable CreatureMasterLootTemplate => this.GetTable(); + public ITable DisenchantMasterLootTemplate => this.GetTable(); + public ITable ProspectingMasterLootTemplate => this.GetTable(); + public ITable MillingMasterLootTemplate => this.GetTable(); + public ITable ReferenceMasterLootTemplate => this.GetTable(); + public ITable SpellMasterLootTemplate => this.GetTable(); + public ITable MailMasterLootTemplate => this.GetTable(); + public ITable GameObjectMasterLootTemplate => this.GetTable(); + public ITable FishingMasterLootTemplate => this.GetTable(); + public ITable SkinningMasterLootTemplate => this.GetTable(); } \ No newline at end of file diff --git a/WoWDatabaseEditor.Common/WDE.TrinityMySqlDatabase/Models/MySqlLootEntry.cs b/WoWDatabaseEditor.Common/WDE.TrinityMySqlDatabase/Models/MySqlLootEntry.cs index 8300ae3a9..e485f331f 100644 --- a/WoWDatabaseEditor.Common/WDE.TrinityMySqlDatabase/Models/MySqlLootEntry.cs +++ b/WoWDatabaseEditor.Common/WDE.TrinityMySqlDatabase/Models/MySqlLootEntry.cs @@ -7,6 +7,8 @@ public abstract class BaseMySqlLootEntry : ILootEntry { public abstract LootSourceType SourceType { get; } + public LootType LootType => Reference != 0 ? LootType.Reference : LootType.Item; + [PrimaryKey] [Column(Name = "Entry")] public uint Entry { get; set; } diff --git a/WoWDatabaseEditor.Common/WDE.TrinityMySqlDatabase/Models/MySqlLootEntryMaster.cs b/WoWDatabaseEditor.Common/WDE.TrinityMySqlDatabase/Models/MySqlLootEntryMaster.cs new file mode 100644 index 000000000..8a5dee3bf --- /dev/null +++ b/WoWDatabaseEditor.Common/WDE.TrinityMySqlDatabase/Models/MySqlLootEntryMaster.cs @@ -0,0 +1,125 @@ +using LinqToDB.Mapping; +using WDE.Common.Database; + +namespace WDE.TrinityMySqlDatabase.Models; + +public abstract class BaseMasterMySqlLootEntry : ILootEntry +{ + public abstract LootSourceType SourceType { get; } + + [PrimaryKey] + [Column(Name = "ItemType")] + public LootType LootType { get; set; } + + [PrimaryKey] + [Column(Name = "Entry")] + public uint Entry { get; set; } + + [Column(Name = "Item")] + public int ItemOrCurrencyId { get; set; } + + public uint Reference => LootType == LootType.Reference ? (uint)ItemOrCurrencyId : 0; + + [Column(Name = "Chance")] + public float Chance { get; set; } + + [Column(Name = "QuestRequired")] + public bool QuestRequired { get; set; } + + [Column(Name = "LootMode")] + public uint LootMode { get; set; } + + [Column(Name = "GroupId")] + public ushort GroupId { get; set; } + + [Column(Name = "MinCount")] + public int MinCount { get; set; } + + [Column(Name = "MaxCount")] + public uint MaxCount { get; set; } + + public int BadLuckProtectionId => 0; + + public uint Build => 0; + + [Column(Name = "Comment")] + public string? Comment { get; set; } + + public ushort MinPatch => 0; + + public ushort MaxPatch => 0; + + public uint ConditionId => 0; +} + +[Table(Name = "creature_loot_template")] +public class CreatureMasterLootTemplate : BaseMasterMySqlLootEntry +{ + public override LootSourceType SourceType => LootSourceType.Creature; +} + +[Table(Name = "gameobject_loot_template")] +public class GameObjectMasterLootTemplate : BaseMasterMySqlLootEntry +{ + public override LootSourceType SourceType => LootSourceType.GameObject; +} + +[Table(Name = "item_loot_template")] +public class ItemMasterLootTemplate : BaseMasterMySqlLootEntry +{ + public override LootSourceType SourceType => LootSourceType.Item; +} + +[Table(Name = "mail_loot_template")] +public class MailMasterLootTemplate : BaseMasterMySqlLootEntry +{ + public override LootSourceType SourceType => LootSourceType.Mail; +} + +[Table(Name = "fishing_loot_template")] +public class FishingMasterLootTemplate : BaseMasterMySqlLootEntry +{ + public override LootSourceType SourceType => LootSourceType.Fishing; +} + +[Table(Name = "skinning_loot_template")] +public class SkinningMasterLootTemplate : BaseMasterMySqlLootEntry +{ + public override LootSourceType SourceType => LootSourceType.Skinning; +} + +[Table(Name = "prospecting_loot_template")] +public class ProspectingMasterLootTemplate : BaseMasterMySqlLootEntry +{ + public override LootSourceType SourceType => LootSourceType.Prospecting; +} + +[Table(Name = "milling_loot_template")] +public class MillingMasterLootTemplate : BaseMasterMySqlLootEntry +{ + public override LootSourceType SourceType => LootSourceType.Milling; +} + +[Table(Name = "disenchant_loot_template")] +public class DisenchantMasterLootTemplate : BaseMasterMySqlLootEntry +{ + public override LootSourceType SourceType => LootSourceType.Disenchant; +} + +[Table(Name = "reference_loot_template")] +public class ReferenceMasterLootTemplate : BaseMasterMySqlLootEntry +{ + public override LootSourceType SourceType => LootSourceType.Reference; +} + +[Table(Name = "pickpocketing_loot_template")] +public class PickpocketingMasterLootTemplate : BaseMasterMySqlLootEntry +{ + public override LootSourceType SourceType => LootSourceType.Pickpocketing; +} + +[Table(Name = "spell_loot_template")] +public class SpellMasterLootTemplate : BaseMasterMySqlLootEntry +{ + public override LootSourceType SourceType => LootSourceType.Spell; +} \ No newline at end of file