mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 10:17:23 +01:00
.
This commit is contained in:
parent
8fbca07f3c
commit
b63b02ae5e
2 changed files with 328 additions and 46 deletions
|
|
@ -49,7 +49,7 @@ public unsafe class DebugTab : ITab
|
|||
private readonly CustomizationService _customization;
|
||||
private readonly JobService _jobs;
|
||||
private readonly CustomizeUnlockManager _customizeUnlocks;
|
||||
private readonly CustomizeUnlockManager _itemUnlocks;
|
||||
private readonly ItemUnlockManager _itemUnlocks;
|
||||
|
||||
private readonly DesignManager _designManager;
|
||||
private readonly DesignFileSystem _designFileSystem;
|
||||
|
|
@ -69,7 +69,8 @@ public unsafe class DebugTab : ITab
|
|||
ActorService actors, ItemManager items, CustomizationService customization, ObjectManager objectManager,
|
||||
DesignFileSystem designFileSystem, DesignManager designManager, StateManager state, Configuration config,
|
||||
PenumbraChangedItemTooltip penumbraTooltip, MetaService metaService, GlamourerIpc ipc, DalamudPluginInterface pluginInterface,
|
||||
AutoDesignManager autoDesignManager, JobService jobs, PhrasingService phrasing, CustomizeUnlockManager customizeUnlocks)
|
||||
AutoDesignManager autoDesignManager, JobService jobs, PhrasingService phrasing, CustomizeUnlockManager customizeUnlocks,
|
||||
ItemUnlockManager itemUnlocks)
|
||||
{
|
||||
_changeCustomizeService = changeCustomizeService;
|
||||
_visorService = visorService;
|
||||
|
|
@ -93,6 +94,7 @@ public unsafe class DebugTab : ITab
|
|||
_jobs = jobs;
|
||||
_phrasing = phrasing;
|
||||
_customizeUnlocks = customizeUnlocks;
|
||||
_itemUnlocks = itemUnlocks;
|
||||
}
|
||||
|
||||
public ReadOnlySpan<byte> Label
|
||||
|
|
@ -1250,6 +1252,7 @@ public unsafe class DebugTab : ITab
|
|||
|
||||
DrawCustomizationUnlocks();
|
||||
DrawItemUnlocks();
|
||||
DrawUnlockableItems();
|
||||
}
|
||||
|
||||
private void DrawCustomizationUnlocks()
|
||||
|
|
@ -1260,7 +1263,7 @@ public unsafe class DebugTab : ITab
|
|||
|
||||
|
||||
using var table = ImRaii.Table("customizationUnlocks", 6,
|
||||
ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY,
|
||||
ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY | ImGuiTableFlags.BordersOuter,
|
||||
new Vector2(ImGui.GetContentRegionAvail().X, 12 * ImGui.GetTextLineHeight()));
|
||||
if (!table)
|
||||
return;
|
||||
|
|
@ -1276,7 +1279,9 @@ public unsafe class DebugTab : ITab
|
|||
ImGuiUtil.DrawTableColumn(t.Value.Data.ToString());
|
||||
ImGuiUtil.DrawTableColumn(t.Value.Name);
|
||||
ImGuiUtil.DrawTableColumn(_customizeUnlocks.IsUnlocked(t.Key, out var time)
|
||||
? time == DateTimeOffset.MaxValue ? "Always" : time.LocalDateTime.ToShortDateString()
|
||||
? time == DateTimeOffset.MaxValue
|
||||
? "Always"
|
||||
: time.LocalDateTime.ToString("g")
|
||||
: "Never");
|
||||
}, _customizeUnlocks.Unlockable.Count);
|
||||
ImGuiClip.DrawEndDummy(remainder, ImGui.GetTextLineHeight());
|
||||
|
|
@ -1284,14 +1289,96 @@ public unsafe class DebugTab : ITab
|
|||
|
||||
private void DrawItemUnlocks()
|
||||
{
|
||||
using var tree = ImRaii.TreeNode("Item");
|
||||
using var tree = ImRaii.TreeNode("Unlocked Items");
|
||||
if (!tree)
|
||||
return;
|
||||
|
||||
|
||||
using var table = ImRaii.Table("itemUnlocks", 6, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg);
|
||||
using var table = ImRaii.Table("itemUnlocks", 5,
|
||||
ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY | ImGuiTableFlags.BordersOuter,
|
||||
new Vector2(ImGui.GetContentRegionAvail().X, 12 * ImGui.GetTextLineHeight()));
|
||||
if (!table)
|
||||
return;
|
||||
|
||||
ImGui.TableSetupColumn("ItemId", ImGuiTableColumnFlags.WidthFixed, 30 * ImGuiHelpers.GlobalScale);
|
||||
ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthFixed, 400 * ImGuiHelpers.GlobalScale);
|
||||
ImGui.TableSetupColumn("Slot", ImGuiTableColumnFlags.WidthFixed, 120 * ImGuiHelpers.GlobalScale);
|
||||
ImGui.TableSetupColumn("Model", ImGuiTableColumnFlags.WidthFixed, 80 * ImGuiHelpers.GlobalScale);
|
||||
ImGui.TableSetupColumn("Unlock", ImGuiTableColumnFlags.WidthFixed, 120 * ImGuiHelpers.GlobalScale);
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeightWithSpacing());
|
||||
ImGui.TableNextRow();
|
||||
var remainder = ImGuiClip.ClippedDraw(_itemUnlocks.Unlocked, skips, t =>
|
||||
{
|
||||
ImGuiUtil.DrawTableColumn(t.Key.ToString());
|
||||
if (_items.ItemService.AwaitedService.TryGetValue(t.Key, out var equip))
|
||||
{
|
||||
ImGuiUtil.DrawTableColumn(equip.Name);
|
||||
ImGuiUtil.DrawTableColumn(equip.Type.ToName());
|
||||
ImGuiUtil.DrawTableColumn(equip.Weapon().ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableNextColumn();
|
||||
}
|
||||
|
||||
ImGuiUtil.DrawTableColumn(_itemUnlocks.IsUnlocked(t.Key, out var time)
|
||||
? time == DateTimeOffset.MaxValue
|
||||
? "Always"
|
||||
: time.LocalDateTime.ToString("g")
|
||||
: "Never");
|
||||
}, _itemUnlocks.Unlocked.Count);
|
||||
ImGuiClip.DrawEndDummy(remainder, ImGui.GetTextLineHeight());
|
||||
}
|
||||
|
||||
private void DrawUnlockableItems()
|
||||
{
|
||||
using var tree = ImRaii.TreeNode("Unlockable Items");
|
||||
if (!tree)
|
||||
return;
|
||||
|
||||
using var table = ImRaii.Table("unlockableItem", 6,
|
||||
ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY | ImGuiTableFlags.BordersOuter,
|
||||
new Vector2(ImGui.GetContentRegionAvail().X, 12 * ImGui.GetTextLineHeight()));
|
||||
if (!table)
|
||||
return;
|
||||
|
||||
ImGui.TableSetupColumn("ItemId", ImGuiTableColumnFlags.WidthFixed, 30 * ImGuiHelpers.GlobalScale);
|
||||
ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthFixed, 400 * ImGuiHelpers.GlobalScale);
|
||||
ImGui.TableSetupColumn("Slot", ImGuiTableColumnFlags.WidthFixed, 120 * ImGuiHelpers.GlobalScale);
|
||||
ImGui.TableSetupColumn("Model", ImGuiTableColumnFlags.WidthFixed, 80 * ImGuiHelpers.GlobalScale);
|
||||
ImGui.TableSetupColumn("Unlock", ImGuiTableColumnFlags.WidthFixed, 120 * ImGuiHelpers.GlobalScale);
|
||||
ImGui.TableSetupColumn("Criteria", ImGuiTableColumnFlags.WidthStretch);
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeightWithSpacing());
|
||||
ImGui.TableNextRow();
|
||||
var remainder = ImGuiClip.ClippedDraw(_itemUnlocks.Unlockable, skips, t =>
|
||||
{
|
||||
ImGuiUtil.DrawTableColumn(t.Key.ToString());
|
||||
if (_items.ItemService.AwaitedService.TryGetValue(t.Key, out var equip))
|
||||
{
|
||||
ImGuiUtil.DrawTableColumn(equip.Name);
|
||||
ImGuiUtil.DrawTableColumn(equip.Type.ToName());
|
||||
ImGuiUtil.DrawTableColumn(equip.Weapon().ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableNextColumn();
|
||||
}
|
||||
|
||||
ImGuiUtil.DrawTableColumn(_itemUnlocks.IsUnlocked(t.Key, out var time)
|
||||
? time == DateTimeOffset.MaxValue
|
||||
? "Always"
|
||||
: time.LocalDateTime.ToString("g")
|
||||
: "Never");
|
||||
ImGuiUtil.DrawTableColumn(t.Value.ToString());
|
||||
}, _itemUnlocks.Unlockable.Count);
|
||||
ImGuiClip.DrawEndDummy(remainder, ImGui.GetTextLineHeight());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
|||
|
|
@ -4,13 +4,11 @@ using System.IO;
|
|||
using Dalamud.Data;
|
||||
using Dalamud.Game;
|
||||
using Dalamud.Game.ClientState;
|
||||
using Dalamud.Hooking;
|
||||
using Dalamud.Utility.Signatures;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
||||
using Glamourer.Services;
|
||||
using Lumina.Excel;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using Achievement = FFXIVClientStructs.FFXIV.Client.Game.UI.Achievement;
|
||||
using Cabinet = Lumina.Excel.GeneratedSheets.Cabinet;
|
||||
|
||||
namespace Glamourer.Unlocks;
|
||||
|
|
@ -23,15 +21,70 @@ public class ItemUnlockManager : ISavable, IDisposable
|
|||
private readonly Framework _framework;
|
||||
private readonly Dictionary<uint, long> _unlocked = new();
|
||||
|
||||
private bool _lastArmoireState;
|
||||
private bool _lastAchievementState;
|
||||
private bool _lastGlamourState;
|
||||
private bool _lastPlateState;
|
||||
private byte _currentInventory;
|
||||
private byte _currentInventoryIndex;
|
||||
|
||||
[Flags]
|
||||
public enum UnlockType : byte
|
||||
{
|
||||
Cabinet,
|
||||
Quest,
|
||||
Achievement,
|
||||
Quest1 = 0x01,
|
||||
Quest2 = 0x02,
|
||||
Achievement = 0x04,
|
||||
Cabinet = 0x08,
|
||||
}
|
||||
|
||||
public readonly IReadOnlyDictionary<uint, (uint, UnlockType)> _unlockable;
|
||||
public readonly record struct UnlockRequirements(uint Quest1, uint Quest2, uint Achievement, ushort State, UnlockType Type)
|
||||
{
|
||||
public override string ToString()
|
||||
{
|
||||
return Type switch
|
||||
{
|
||||
UnlockType.Quest1 => $"Quest {Quest1}",
|
||||
UnlockType.Quest1 | UnlockType.Quest2 => $"Quests {Quest1} & {Quest2}",
|
||||
UnlockType.Achievement => $"Achievement {Achievement}",
|
||||
UnlockType.Quest1 | UnlockType.Achievement => $"Quest {Quest1} & Achievement {Achievement}",
|
||||
UnlockType.Quest1 | UnlockType.Quest2 | UnlockType.Achievement => $"Quests {Quest1} & {Quest2}, Achievement {Achievement}",
|
||||
UnlockType.Cabinet => $"Cabinet {Quest1}",
|
||||
_ => string.Empty,
|
||||
};
|
||||
}
|
||||
|
||||
public unsafe bool IsUnlocked(ItemUnlockManager manager)
|
||||
{
|
||||
if (Type == 0)
|
||||
return true;
|
||||
|
||||
var uiState = UIState.Instance();
|
||||
if (uiState == null)
|
||||
return false;
|
||||
|
||||
bool CheckQuest(uint quest)
|
||||
=> uiState->IsUnlockLinkUnlockedOrQuestCompleted(quest);
|
||||
|
||||
// TODO ClientStructs
|
||||
bool CheckAchievement(uint achievement)
|
||||
=> false;
|
||||
|
||||
return Type switch
|
||||
{
|
||||
UnlockType.Quest1 => CheckQuest(Quest1),
|
||||
UnlockType.Quest1 | UnlockType.Quest2 => CheckQuest(Quest1) && CheckQuest(Quest2),
|
||||
UnlockType.Achievement => CheckAchievement(Achievement),
|
||||
UnlockType.Quest1 | UnlockType.Achievement => CheckQuest(Quest1) && CheckAchievement(Achievement),
|
||||
UnlockType.Quest1 | UnlockType.Quest2 | UnlockType.Achievement => CheckQuest(Quest1)
|
||||
&& CheckQuest(Quest2)
|
||||
&& CheckAchievement(Achievement),
|
||||
UnlockType.Cabinet => uiState->Cabinet.IsCabinetLoaded() && uiState->Cabinet.IsItemInCabinet((int)Quest1),
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public readonly IReadOnlyDictionary<uint, UnlockRequirements> Unlockable;
|
||||
|
||||
public IReadOnlyDictionary<uint, long> Unlocked
|
||||
=> _unlocked;
|
||||
|
|
@ -43,7 +96,7 @@ public class ItemUnlockManager : ISavable, IDisposable
|
|||
_items = items;
|
||||
_clientState = clientState;
|
||||
_framework = framework;
|
||||
_unlockable = CreateUnlockData(gameData, items);
|
||||
Unlockable = CreateUnlockData(gameData, items);
|
||||
Load();
|
||||
_clientState.Login += OnLogin;
|
||||
_framework.Update += OnFramework;
|
||||
|
|
@ -52,38 +105,156 @@ public class ItemUnlockManager : ISavable, IDisposable
|
|||
|
||||
//private Achievement.AchievementState _achievementState = Achievement.AchievementState.Invalid;
|
||||
|
||||
private static readonly InventoryType[] ScannableInventories =
|
||||
{
|
||||
InventoryType.Inventory1,
|
||||
InventoryType.Inventory2,
|
||||
InventoryType.Inventory3,
|
||||
InventoryType.Inventory4,
|
||||
InventoryType.EquippedItems,
|
||||
InventoryType.Mail,
|
||||
InventoryType.ArmoryOffHand,
|
||||
InventoryType.ArmoryHead,
|
||||
InventoryType.ArmoryBody,
|
||||
InventoryType.ArmoryHands,
|
||||
InventoryType.ArmoryLegs,
|
||||
InventoryType.ArmoryFeets,
|
||||
InventoryType.ArmoryEar,
|
||||
InventoryType.ArmoryNeck,
|
||||
InventoryType.ArmoryWrist,
|
||||
InventoryType.ArmoryRings,
|
||||
InventoryType.ArmoryMainHand,
|
||||
InventoryType.SaddleBag1,
|
||||
InventoryType.SaddleBag2,
|
||||
InventoryType.PremiumSaddleBag1,
|
||||
InventoryType.PremiumSaddleBag2,
|
||||
InventoryType.RetainerPage1,
|
||||
InventoryType.RetainerPage2,
|
||||
InventoryType.RetainerPage3,
|
||||
InventoryType.RetainerPage4,
|
||||
InventoryType.RetainerPage5,
|
||||
InventoryType.RetainerPage6,
|
||||
InventoryType.RetainerPage7,
|
||||
InventoryType.RetainerEquippedItems,
|
||||
InventoryType.RetainerMarket,
|
||||
};
|
||||
|
||||
private unsafe void OnFramework(Framework _)
|
||||
{
|
||||
//var achievement = Achievement.Instance();
|
||||
var uiState = UIState.Instance();
|
||||
}
|
||||
|
||||
public bool IsUnlocked(uint itemId)
|
||||
{
|
||||
// Pseudo items are always unlocked.
|
||||
if (itemId >= _items.ItemSheet.RowCount)
|
||||
return true;
|
||||
|
||||
if (_unlocked.ContainsKey(itemId))
|
||||
return true;
|
||||
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
public unsafe bool IsGameUnlocked(uint id, UnlockType type)
|
||||
{
|
||||
var uiState = UIState.Instance();
|
||||
if (uiState == null)
|
||||
return false;
|
||||
return;
|
||||
|
||||
return type switch
|
||||
var scan = false;
|
||||
var newArmoireState = uiState->Cabinet.IsCabinetLoaded();
|
||||
if (newArmoireState != _lastArmoireState)
|
||||
{
|
||||
UnlockType.Cabinet => uiState->Cabinet.IsCabinetLoaded() && uiState->Cabinet.IsItemInCabinet((int)id),
|
||||
UnlockType.Quest => uiState->IsUnlockLinkUnlockedOrQuestCompleted(id),
|
||||
UnlockType.Achievement => false,
|
||||
_ => false,
|
||||
};
|
||||
_lastArmoireState = newArmoireState;
|
||||
scan |= newArmoireState;
|
||||
}
|
||||
|
||||
//var newAchievementState = uiState->Achievement.IsAchievementLoaded();
|
||||
//if (newAchievementState != _lastAchievementState)
|
||||
//{
|
||||
// _lastAchievementState = newAchievementState;
|
||||
// scan |= newAchievementState;
|
||||
//}
|
||||
|
||||
if (scan)
|
||||
Scan();
|
||||
|
||||
var time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||
|
||||
bool AddItem(uint itemId)
|
||||
=> _items.ItemService.AwaitedService.TryGetValue(itemId, out var equip) && _unlocked.TryAdd(equip.Id, time);
|
||||
|
||||
var mirageManager = MirageManager.Instance();
|
||||
var changes = false;
|
||||
if (mirageManager != null)
|
||||
{
|
||||
var newGlamourState = mirageManager->PrismBoxLoaded;
|
||||
if (newGlamourState != _lastGlamourState)
|
||||
{
|
||||
_lastGlamourState = newGlamourState;
|
||||
// TODO: Make independent from hardcoded value
|
||||
var span = new ReadOnlySpan<uint>(mirageManager->PrismBoxItemIds, 800);
|
||||
foreach (var item in span)
|
||||
changes |= AddItem(item);
|
||||
}
|
||||
|
||||
var newPlateState = mirageManager->GlamourPlatesLoaded;
|
||||
if (newPlateState != _lastPlateState)
|
||||
{
|
||||
_lastPlateState = newPlateState;
|
||||
foreach (var plate in mirageManager->GlamourPlatesSpan)
|
||||
{
|
||||
// TODO: Make independent from hardcoded value
|
||||
var span = new ReadOnlySpan<uint>(plate.ItemIds, 12);
|
||||
foreach (var item in span)
|
||||
changes |= AddItem(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var inventoryManager = InventoryManager.Instance();
|
||||
if (inventoryManager != null)
|
||||
{
|
||||
var type = ScannableInventories[_currentInventory];
|
||||
var container = inventoryManager->GetInventoryContainer(type);
|
||||
if (container != null && container->Loaded != 0 && _currentInventoryIndex < container->Size)
|
||||
{
|
||||
var item = container->GetInventorySlot(_currentInventoryIndex++);
|
||||
if (item != null)
|
||||
{
|
||||
changes |= AddItem(item->ItemID);
|
||||
changes |= AddItem(item->GlamourID);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentInventory = (byte)(_currentInventory + 1 == ScannableInventories.Length ? 0 : _currentInventory + 1);
|
||||
_currentInventoryIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (changes)
|
||||
Save();
|
||||
}
|
||||
|
||||
public bool IsUnlocked(uint itemId, out DateTimeOffset time)
|
||||
{
|
||||
// Pseudo items are always unlocked.
|
||||
if (itemId >= _items.ItemSheet.RowCount)
|
||||
{
|
||||
time = DateTimeOffset.MaxValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_unlocked.TryGetValue(itemId, out var t))
|
||||
{
|
||||
time = DateTimeOffset.FromUnixTimeMilliseconds(t);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsGameUnlocked(itemId))
|
||||
{
|
||||
time = DateTimeOffset.UtcNow;
|
||||
_unlocked.TryAdd(itemId, time.ToUnixTimeMilliseconds());
|
||||
Save();
|
||||
return true;
|
||||
}
|
||||
|
||||
time = DateTimeOffset.MinValue;
|
||||
return false;
|
||||
}
|
||||
|
||||
public unsafe bool IsGameUnlocked(uint itemId)
|
||||
{
|
||||
if (Unlockable.TryGetValue(itemId, out var req))
|
||||
return req.IsUnlocked(this);
|
||||
|
||||
// TODO inventory
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
@ -94,7 +265,18 @@ public class ItemUnlockManager : ISavable, IDisposable
|
|||
|
||||
public void Scan()
|
||||
{
|
||||
// TODO
|
||||
var time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||
var changes = false;
|
||||
foreach (var (itemId, unlock) in Unlockable)
|
||||
{
|
||||
if (unlock.IsUnlocked(this))
|
||||
changes |= _unlocked.TryAdd(itemId, time);
|
||||
}
|
||||
|
||||
// TODO inventories
|
||||
|
||||
if (changes)
|
||||
Save();
|
||||
}
|
||||
|
||||
public string ToFilename(FilenameService fileNames)
|
||||
|
|
@ -118,18 +300,31 @@ public class ItemUnlockManager : ISavable, IDisposable
|
|||
private void OnLogin(object? _, EventArgs _2)
|
||||
=> Scan();
|
||||
|
||||
private static Dictionary<uint, (uint, UnlockType)> CreateUnlockData(DataManager gameData, ItemManager items)
|
||||
private static Dictionary<uint, UnlockRequirements> CreateUnlockData(DataManager gameData, ItemManager items)
|
||||
{
|
||||
var ret = new Dictionary<uint, (uint, UnlockType)>();
|
||||
var ret = new Dictionary<uint, UnlockRequirements>();
|
||||
var cabinet = gameData.GetExcelSheet<Cabinet>()!;
|
||||
foreach (var row in cabinet)
|
||||
{
|
||||
if (items.ItemService.AwaitedService.TryGetValue(row.Item.Row, out var item))
|
||||
ret.TryAdd(item.Id, (row.RowId, UnlockType.Cabinet));
|
||||
ret.TryAdd(item.Id, new UnlockRequirements(row.RowId, 0, 0, 0, UnlockType.Cabinet));
|
||||
}
|
||||
|
||||
var gilShop = gameData.GetExcelSheet<GilShopItem>()!;
|
||||
// TODO
|
||||
foreach (var row in gilShop)
|
||||
{
|
||||
if (!items.ItemService.AwaitedService.TryGetValue(row.Item.Row, out var item))
|
||||
continue;
|
||||
|
||||
var quest1 = row.QuestRequired[0].Row;
|
||||
var quest2 = row.QuestRequired[1].Row;
|
||||
var achievement = row.AchievementRequired.Row;
|
||||
var state = row.StateRequired;
|
||||
var type = (quest1 != 0 ? UnlockType.Quest1 : 0)
|
||||
| (quest2 != 0 ? UnlockType.Quest2 : 0)
|
||||
| (achievement != 0 ? UnlockType.Achievement : 0);
|
||||
ret.TryAdd(item.Id, new UnlockRequirements(quest1, quest2, achievement, state, type));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue