Skip to content

Commit 6046adb

Browse files
committed
[Loot] Fix bug in loot
1 parent 69c7b41 commit 6046adb

File tree

14 files changed

+331
-19
lines changed

14 files changed

+331
-19
lines changed

Modules/WDE.HttpDatabase/Models/MySqlLootEntry.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ namespace WDE.HttpDatabase.Models;
66
public class JsonLootEntry : ILootEntry
77
{
88
public LootSourceType SourceType { get; set; }
9+
public LootType LootType { get; set; }
910
public uint Entry { get; set; }
1011
public int ItemOrCurrencyId { get; set; }
1112
public uint Reference { get; set; }

Modules/WDE.LootEditor/Editor/Standalone/StandaloneLootEditorToolBar.axaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<CompletionComboBox
2323
IsEnabled="{CompiledBinding CanChangeLootType}"
2424
SelectedItem="{CompiledBinding LootType, Mode=TwoWay}"
25-
controls:Extensions.EnumType="{x:Type database:LootSourceType}" />
25+
Items="{CompiledBinding SupportedLootTypes}" />
2626

2727
<Border Width="20" />
2828

Modules/WDE.LootEditor/Editor/Standalone/StandaloneLootEditorViewModel.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ public LootSourceType LootType
5858
}
5959
}
6060

61+
public IReadOnlyList<LootSourceType> SupportedLootTypes { get; }
62+
6163
[Notify] private bool canChangeLootType = true;
6264
[Notify] private bool canChangeEntry = true;
6365
[Notify] private uint solutionEntry;
@@ -192,6 +194,7 @@ public StandaloneLootEditorViewModel(
192194
ITextDocumentService textDocumentService,
193195
IParameterFactory parameterFactory,
194196
ICurrentCoreVersion currentCoreVersion,
197+
ILootEditorFeatures lootEditorFeatures,
195198
PerDatabaseTableLootSolutionItem? solutionItem = null
196199
)
197200
{
@@ -202,6 +205,7 @@ public StandaloneLootEditorViewModel(
202205
this.parameterPickerService = parameterPickerService;
203206
this.messageBoxService = messageBoxService;
204207
this.currentCoreVersion = currentCoreVersion;
208+
SupportedLootTypes = lootEditorFeatures.SupportedTypes;
205209
legacyDifficulties[0] = DifficultyViewModel.Legacy(0, "default");
206210
legacyDifficulties[1] = DifficultyViewModel.Legacy(1, "heroic dung/25 raid");
207211
legacyDifficulties[2] = DifficultyViewModel.Legacy(2, "10 heroic raid");

Modules/WDE.LootEditor/Editor/ViewModels/LootEditorViewModel.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,7 +1086,7 @@ private async Task UnloadLoot(LootSourceType type, LootEntry menu)
10861086

10871087
private IReadOnlyList<LootEntry> Roots =>
10881088
(LootEditingMode == LootEditingMode.PerDatabaseTable) ? PerDatabaseSolutionItems :
1089-
Loots.Where(x => x.LootSourceType != LootSourceType.Reference || (uint)x.LootEntry == perEntitySolutionItem!.Entry)
1089+
Loots.Where(x => x.LootSourceType != LootSourceType.Reference || perEntitySolutionItem!.Type == LootSourceType.Reference && (uint)x.LootEntry == perEntitySolutionItem!.Entry)
10901090
.Select(x => x.LootEntry)
10911091
.ToList();
10921092

@@ -1128,7 +1128,7 @@ private bool VerifyDuplicateKeys()
11281128
{
11291129
var loot = lootGroup.LootItems[lootIndex];
11301130
loot.IsDuplicate = false;
1131-
var item = loot.ItemOrCurrencyId.Value;
1131+
var item = loot.IsReference ? loot.ReferenceEntry : loot.ItemOrCurrencyId.Value;
11321132
var minPatch = loot.MinPatch.Value;
11331133
if (!keys.Add((item, minPatch)))
11341134
{

Modules/WDE.LootEditor/Editor/ViewModels/LootItemViewModel.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ public LootModel ToModel()
249249
SourceType = Parent.LootSourceType,
250250
Entry = (uint)Parent.LootEntry,
251251
ItemOrCurrencyId = (int)ItemOrCurrencyId.Value,
252+
LootType = IsReference ? LootType.Reference : LootType.Item,
252253
Chance = Math.Abs(Chance.Value),
253254
QuestRequired = Chance.Value < 0,
254255
LootMode = (uint)LootMode.Value,

Modules/WDE.LootEditor/QueryGenerator/CmangosLootQueryGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public IQuery GenerateQuery(IReadOnlyList<LootGroupModel> models)
6464
.BulkInsert(group.Items.Select(x => new
6565
{
6666
entry = x.Loot.Entry,
67-
item = x.Loot.ItemOrCurrencyId,
67+
item = x.Loot.IsReference() && x.Loot.ItemOrCurrencyId == 0 ? (long)x.Loot.Reference : x.Loot.ItemOrCurrencyId,
6868
ChanceOrQuestChance = (x.Loot.QuestRequired ? -1 : 1) * x.Loot.Chance,
6969
groupid = x.Loot.GroupId,
7070
mincountOrRef = x.Loot.IsReference() ? -(int)x.Loot.Reference : x.Loot.MinCount,

Modules/WDE.LootEditor/QueryGenerator/TrinityLootQueryGenerator.cs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ public IQuery GenerateUpdateLootIds(LootSourceType sourceType, uint solutionEntr
129129
}
130130
}
131131

132-
[RequiresCore("TrinityMaster", "TrinityWrath", "Azeroth")]
132+
[RequiresCore("TrinityWrath", "Azeroth")]
133133
[AutoRegister]
134134
[SingleInstance]
135135
public class TrinityLootQueryGenerator : BaseTrinityLootQueryGenerator
@@ -143,7 +143,7 @@ protected override object CreateDatabaseObjectRow(LootModel x)
143143
return new
144144
{
145145
Entry = x.Loot.Entry,
146-
Item = x.Loot.ItemOrCurrencyId,
146+
Item = x.Loot.IsReference() && x.Loot.ItemOrCurrencyId == 0 ? (long)x.Loot.Reference : x.Loot.ItemOrCurrencyId,
147147
Reference = x.Loot.Reference,
148148
Chance = x.Loot.Chance,
149149
QuestRequired = x.Loot.QuestRequired,
@@ -156,6 +156,33 @@ protected override object CreateDatabaseObjectRow(LootModel x)
156156
}
157157
}
158158

159+
[RequiresCore("TrinityMaster")]
160+
[AutoRegister]
161+
[SingleInstance]
162+
public class TrinityMasterLootQueryGenerator : BaseTrinityLootQueryGenerator
163+
{
164+
public TrinityMasterLootQueryGenerator(IConditionQueryGenerator conditionQueryGenerator, ICurrentCoreVersion currentCoreVersion, ILootEditorFeatures editorFeatures) : base(conditionQueryGenerator, currentCoreVersion, editorFeatures)
165+
{
166+
}
167+
168+
protected override object CreateDatabaseObjectRow(LootModel x)
169+
{
170+
return new
171+
{
172+
Entry = x.Loot.Entry,
173+
Item = x.Loot.LootType == LootType.Reference ? x.Loot.Reference : (long)x.Loot.ItemOrCurrencyId,
174+
ItemType = (int)x.Loot.LootType,
175+
Chance = x.Loot.Chance,
176+
QuestRequired = x.Loot.QuestRequired,
177+
LootMode = x.Loot.LootMode,
178+
GroupId = x.Loot.GroupId,
179+
MinCount = x.Loot.MinCount,
180+
MaxCount = x.Loot.MaxCount,
181+
Comment = x.Loot.Comment
182+
};
183+
}
184+
}
185+
159186
[RequiresCore("TrinityCata")]
160187
[AutoRegister]
161188
[SingleInstance]
@@ -170,7 +197,7 @@ protected override object CreateDatabaseObjectRow(LootModel x)
170197
return new
171198
{
172199
Entry = x.Loot.Entry,
173-
Item = Math.Abs(x.Loot.ItemOrCurrencyId),
200+
Item = x.Loot.IsReference() && x.Loot.ItemOrCurrencyId == 0 ? (long)x.Loot.Reference : Math.Abs(x.Loot.ItemOrCurrencyId),
174201
IsCurrency = x.Loot.ItemOrCurrencyId < 0,
175202
Reference = x.Loot.Reference,
176203
Chance = x.Loot.Chance,

WoWDatabaseEditor.Common/WDE.CMMySqlDatabase/Models/Loot.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ namespace WDE.CMMySqlDatabase.Models;
66
public abstract class BaseLootTemplate : ILootEntry
77
{
88
public abstract LootSourceType SourceType { get; }
9-
9+
10+
public LootType LootType => Reference != 0 ? LootType.Reference : LootType.Item;
11+
1012
[PrimaryKey]
1113
[Column(Name = "entry")]
1214
public uint Entry { get; set; }

WoWDatabaseEditor.Common/WDE.Common/Database/LootType.cs

Lines changed: 0 additions & 6 deletions
This file was deleted.

WoWDatabaseEditor.Common/WDE.Common/Utils/AsyncAutoCommand.cs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Prism.Commands;
88
using WDE.Common.Annotations;
99
using WDE.Common.Exceptions;
10+
using WDE.Common.Services;
1011
using WDE.Common.Services.MessageBox;
1112
using WDE.Common.Tasks;
1213

@@ -46,7 +47,14 @@ public AsyncAutoCommand(Func<Task> execute,
4647
{
4748
LOG.LogError(e, "Error in {0} at {1}:{2}", caller, callerFile, callerLineNumber);
4849
}
49-
onException?.Invoke(e);
50+
if (onException == null)
51+
{
52+
var service = DI.Resolve<IMessageBoxService>();
53+
if (service != null)
54+
GlobalApplication.MainThread.Dispatch(() => CommandExtensions.ShowError(service, e, null));
55+
}
56+
else
57+
onException?.Invoke(e);
5058
},
5159
continueOnCapturedContext);
5260
}
@@ -116,7 +124,14 @@ public AsyncAutoCommand([NotNull]
116124
e =>
117125
{
118126
IsBusy = false;
119-
onException?.Invoke(e);
127+
if (onException == null)
128+
{
129+
var service = DI.Resolve<IMessageBoxService>();
130+
if (service != null)
131+
GlobalApplication.MainThread.Dispatch(() => CommandExtensions.ShowError(service, e, null));
132+
}
133+
else
134+
onException?.Invoke(e);
120135
},
121136
continueOnCapturedContext);
122137
}
@@ -290,7 +305,7 @@ public static IAsyncCommand<R> WrapMessageBox<T, R>(this IAsyncCommand<R> cmd, I
290305
});
291306
}
292307

293-
private static async Task ShowError(IMessageBoxService messageBoxService, Exception e, string? header,
308+
internal static async Task ShowError(IMessageBoxService messageBoxService, Exception e, string? header,
294309
[CallerMemberName] string? caller = null,
295310
[CallerFilePath] string? callerFile = null,
296311
[CallerLineNumber] int? callerLineNumber = null)

WoWDatabaseEditor.Common/WDE.TrinityMySqlDatabase/Database/TrinityMasterMySqlDatabaseProvider.cs

Lines changed: 130 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,8 @@ public override async Task<IReadOnlyList<ICreatureTemplateAddon>> GetCreatureTem
320320

321321
public override async Task<ICreatureTemplateAddon?> GetCreatureTemplateAddon(uint entry)
322322
{
323-
await using var model = Database();
324-
return await model.CreatureTemplateAddon.FirstOrDefaultAsync<ICreatureTemplateAddon>(x => x.Entry == entry);
323+
using var model = Database();
324+
return model.CreatureTemplateAddon.FirstOrDefault<ICreatureTemplateAddon>(x => x.Entry == entry);
325325
}
326326

327327
public override async Task<IReadOnlyList<IPlayerChoice>?> GetPlayerChoicesAsync()
@@ -542,4 +542,132 @@ public override async Task<IReadOnlyList<IConversationActor>> GetConversationAct
542542
await using var model = Database();
543543
return await model.ConversationActor.OrderBy(x => x.ConversationId).ThenBy(x => x.Idx).ToListAsync<IConversationActor>();
544544
}
545+
546+
547+
public override async Task<IReadOnlyList<ILootEntry>> GetLoot(LootSourceType type)
548+
{
549+
await using var database = Database();
550+
switch (type)
551+
{
552+
case LootSourceType.Item:
553+
return await database.ItemMasterLootTemplate.OrderBy(x => x.Entry)
554+
.ThenBy(x => x.GroupId)
555+
.ThenBy(x => x.ItemOrCurrencyId)
556+
.ToListAsync<ILootEntry>();
557+
case LootSourceType.GameObject:
558+
return await database.GameObjectMasterLootTemplate.OrderBy(x => x.Entry)
559+
.ThenBy(x => x.GroupId)
560+
.ThenBy(x => x.ItemOrCurrencyId)
561+
.ToListAsync<ILootEntry>();
562+
case LootSourceType.Fishing:
563+
return await database.FishingMasterLootTemplate.OrderBy(x => x.Entry)
564+
.ThenBy(x => x.GroupId)
565+
.ThenBy(x => x.ItemOrCurrencyId)
566+
.ToListAsync<ILootEntry>();
567+
case LootSourceType.Pickpocketing:
568+
return await database.PickpocketingMasterLootTemplate.OrderBy(x => x.Entry)
569+
.ThenBy(x => x.GroupId)
570+
.ThenBy(x => x.ItemOrCurrencyId)
571+
.ToListAsync<ILootEntry>();
572+
case LootSourceType.Skinning:
573+
return await database.SkinningMasterLootTemplate.OrderBy(x => x.Entry)
574+
.ThenBy(x => x.GroupId)
575+
.ThenBy(x => x.ItemOrCurrencyId)
576+
.ToListAsync<ILootEntry>();
577+
case LootSourceType.Disenchant:
578+
return await database.DisenchantMasterLootTemplate.OrderBy(x => x.Entry)
579+
.ThenBy(x => x.GroupId)
580+
.ThenBy(x => x.ItemOrCurrencyId)
581+
.ToListAsync<ILootEntry>();
582+
case LootSourceType.Prospecting:
583+
return await database.ProspectingMasterLootTemplate.OrderBy(x => x.Entry)
584+
.ThenBy(x => x.GroupId)
585+
.ThenBy(x => x.ItemOrCurrencyId)
586+
.ToListAsync<ILootEntry>();
587+
case LootSourceType.Milling:
588+
return await database.MillingMasterLootTemplate.OrderBy(x => x.Entry)
589+
.ThenBy(x => x.GroupId)
590+
.ThenBy(x => x.ItemOrCurrencyId)
591+
.ToListAsync<ILootEntry>();
592+
case LootSourceType.Reference:
593+
return await database.ReferenceMasterLootTemplate.OrderBy(x => x.Entry)
594+
.ThenBy(x => x.GroupId)
595+
.ThenBy(x => x.ItemOrCurrencyId)
596+
.ToListAsync<ILootEntry>();
597+
case LootSourceType.Creature:
598+
return await database.CreatureMasterLootTemplate.OrderBy(x => x.Entry)
599+
.ThenBy(x => x.GroupId)
600+
.ThenBy(x => x.ItemOrCurrencyId)
601+
.ToListAsync<ILootEntry>();
602+
case LootSourceType.Mail:
603+
return await database.MailMasterLootTemplate.OrderBy(x => x.Entry)
604+
.ThenBy(x => x.GroupId)
605+
.ThenBy(x => x.ItemOrCurrencyId)
606+
.ToListAsync<ILootEntry>();
607+
case LootSourceType.Spell:
608+
return await database.SpellMasterLootTemplate.OrderBy(x => x.Entry)
609+
.ThenBy(x => x.GroupId)
610+
.ThenBy(x => x.ItemOrCurrencyId)
611+
.ToListAsync<ILootEntry>();
612+
default:
613+
throw new ArgumentOutOfRangeException(nameof(type), type, null);
614+
}
615+
}
616+
617+
public override async Task<IReadOnlyList<ILootEntry>> GetReferenceLootCrossReference(uint lootId)
618+
{
619+
if (lootId == 0)
620+
return Array.Empty<ILootEntry>();
621+
await using var database = Database();
622+
var loot = new[]
623+
{
624+
await database.CreatureMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync<ILootEntry>(),
625+
await database.GameObjectMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync<ILootEntry>(),
626+
await database.ItemMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync<ILootEntry>(),
627+
await database.FishingMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync<ILootEntry>(),
628+
await database.PickpocketingMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync<ILootEntry>(),
629+
await database.SkinningMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync<ILootEntry>(),
630+
await database.DisenchantMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync<ILootEntry>(),
631+
await database.ProspectingMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync<ILootEntry>(),
632+
await database.MillingMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync<ILootEntry>(),
633+
await database.MailMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync<ILootEntry>(),
634+
await database.SpellMasterLootTemplate.Where(x => x.Reference == lootId).ToListAsync<ILootEntry>(),
635+
await database.ReferenceLootTemplate.Where(x => x.Reference == lootId).ToListAsync<ILootEntry>(),
636+
};
637+
return loot.SelectMany(x => x).ToList();
638+
}
639+
640+
public override async Task<IReadOnlyList<ILootEntry>> GetLoot(LootSourceType type, uint entry)
641+
{
642+
await using var database = Database();
643+
switch (type)
644+
{
645+
case LootSourceType.Item:
646+
return await database.ItemMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync<ILootEntry>();
647+
case LootSourceType.GameObject:
648+
return await database.GameObjectMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync<ILootEntry>();
649+
case LootSourceType.Fishing:
650+
return await database.FishingMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync<ILootEntry>();
651+
case LootSourceType.Pickpocketing:
652+
return await database.PickpocketingMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync<ILootEntry>();
653+
case LootSourceType.Skinning:
654+
return await database.SkinningMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync<ILootEntry>();
655+
case LootSourceType.Disenchant:
656+
return await database.DisenchantMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync<ILootEntry>();
657+
case LootSourceType.Prospecting:
658+
return await database.ProspectingMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync<ILootEntry>();
659+
case LootSourceType.Milling:
660+
return await database.MillingMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync<ILootEntry>();
661+
case LootSourceType.Reference:
662+
return await database.ReferenceMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync<ILootEntry>();
663+
case LootSourceType.Creature:
664+
return await database.CreatureMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync<ILootEntry>();
665+
case LootSourceType.Mail:
666+
return await database.MailMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync<ILootEntry>();
667+
case LootSourceType.Spell:
668+
return await database.SpellMasterLootTemplate.Where(x => x.Entry == entry).ToListAsync<ILootEntry>();
669+
default:
670+
throw new ArgumentOutOfRangeException(nameof(type), type, null);
671+
}
672+
}
545673
}

WoWDatabaseEditor.Common/WDE.TrinityMySqlDatabase/Models/Databases/TrinityMasterDatabase.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,17 @@ public class TrinityMasterDatabase : BaseTrinityDatabase
2727
public ITable<MasterWaypointData> WaypointData => this.GetTable<MasterWaypointData>();
2828
public ITable<MySqlConditionLineMaster> ConditionsMaster => this.GetTable<MySqlConditionLineMaster>();
2929
public ITable<MySqlConversationActor> ConversationActor => this.GetTable<MySqlConversationActor>();
30+
31+
public ITable<ItemMasterLootTemplate> ItemMasterLootTemplate => this.GetTable<ItemMasterLootTemplate>();
32+
public ITable<PickpocketingMasterLootTemplate> PickpocketingMasterLootTemplate => this.GetTable<PickpocketingMasterLootTemplate>();
33+
public ITable<CreatureMasterLootTemplate> CreatureMasterLootTemplate => this.GetTable<CreatureMasterLootTemplate>();
34+
public ITable<DisenchantMasterLootTemplate> DisenchantMasterLootTemplate => this.GetTable<DisenchantMasterLootTemplate>();
35+
public ITable<ProspectingMasterLootTemplate> ProspectingMasterLootTemplate => this.GetTable<ProspectingMasterLootTemplate>();
36+
public ITable<MillingMasterLootTemplate> MillingMasterLootTemplate => this.GetTable<MillingMasterLootTemplate>();
37+
public ITable<ReferenceMasterLootTemplate> ReferenceMasterLootTemplate => this.GetTable<ReferenceMasterLootTemplate>();
38+
public ITable<SpellMasterLootTemplate> SpellMasterLootTemplate => this.GetTable<SpellMasterLootTemplate>();
39+
public ITable<MailMasterLootTemplate> MailMasterLootTemplate => this.GetTable<MailMasterLootTemplate>();
40+
public ITable<GameObjectMasterLootTemplate> GameObjectMasterLootTemplate => this.GetTable<GameObjectMasterLootTemplate>();
41+
public ITable<FishingMasterLootTemplate> FishingMasterLootTemplate => this.GetTable<FishingMasterLootTemplate>();
42+
public ITable<SkinningMasterLootTemplate> SkinningMasterLootTemplate => this.GetTable<SkinningMasterLootTemplate>();
3043
}

WoWDatabaseEditor.Common/WDE.TrinityMySqlDatabase/Models/MySqlLootEntry.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ public abstract class BaseMySqlLootEntry : ILootEntry
77
{
88
public abstract LootSourceType SourceType { get; }
99

10+
public LootType LootType => Reference != 0 ? LootType.Reference : LootType.Item;
11+
1012
[PrimaryKey]
1113
[Column(Name = "Entry")]
1214
public uint Entry { get; set; }

0 commit comments

Comments
 (0)