182 lines
7.1 KiB
C#
182 lines
7.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Immutable;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Runtime.CompilerServices;
|
|
using Dalamud.Game;
|
|
using Dalamud.Plugin.Services;
|
|
using Dalamud.Utility;
|
|
using Lumina.Excel.Sheets;
|
|
using Questionable.Model.Questing;
|
|
|
|
namespace Questionable.Data;
|
|
|
|
internal sealed class TerritoryData
|
|
{
|
|
public sealed record ContentFinderConditionData(uint ContentFinderConditionId, string Name, uint TerritoryId, ushort RequiredItemLevel)
|
|
{
|
|
public ContentFinderConditionData(ContentFinderCondition condition, ClientLanguage clientLanguage)
|
|
: this(condition.RowId, FixName(condition.Name.ToDalamudString().ToString(), clientLanguage), condition.TerritoryType.RowId, condition.ItemLevelRequired)
|
|
{
|
|
}
|
|
}
|
|
|
|
private readonly ImmutableDictionary<uint, string> _territoryNames;
|
|
|
|
private readonly ImmutableHashSet<ushort> _territoriesWithMount;
|
|
|
|
private readonly ImmutableDictionary<ushort, uint> _dutyTerritories;
|
|
|
|
private readonly ImmutableDictionary<uint, string> _instanceNames;
|
|
|
|
private readonly ImmutableDictionary<uint, ContentFinderConditionData> _contentFinderConditions;
|
|
|
|
private readonly ImmutableDictionary<(ElementId QuestId, byte Index), uint> _questBattlesToContentFinderCondition;
|
|
|
|
public TerritoryData(IDataManager dataManager)
|
|
{
|
|
_territoryNames = (from x in dataManager.GetExcelSheet<TerritoryType>()
|
|
where x.RowId != 0
|
|
select new
|
|
{
|
|
RowId = x.RowId,
|
|
Name = (x.PlaceName.ValueNullable?.Name.ToString() ?? x.PlaceNameZone.ValueNullable?.Name.ToString())
|
|
} into x
|
|
where !string.IsNullOrEmpty(x.Name)
|
|
select x).ToImmutableDictionary(x => x.RowId, x => x.Name);
|
|
_territoriesWithMount = (from x in dataManager.GetExcelSheet<TerritoryType>()
|
|
where x.RowId != 0 && x.Mount
|
|
select (ushort)x.RowId).ToImmutableHashSet();
|
|
_dutyTerritories = (from x in dataManager.GetExcelSheet<TerritoryType>()
|
|
where x.RowId != 0 && x.ContentFinderCondition.RowId != 0
|
|
select x).ToImmutableDictionary((TerritoryType x) => (ushort)x.RowId, (TerritoryType x) => x.ContentFinderCondition.Value.ContentType.RowId);
|
|
_instanceNames = (from x in dataManager.GetExcelSheet<ContentFinderCondition>()
|
|
where x.RowId != 0 && x.Content.RowId != 0 && x.ContentLinkType == 1 && x.ContentType.RowId != 6
|
|
select x).ToImmutableDictionary((ContentFinderCondition x) => x.Content.RowId, (ContentFinderCondition x) => x.Name.ToDalamudString().ToString());
|
|
_contentFinderConditions = (from x in dataManager.GetExcelSheet<ContentFinderCondition>().Where(delegate(ContentFinderCondition x)
|
|
{
|
|
bool flag = x.RowId != 0 && x.Content.RowId != 0;
|
|
if (flag)
|
|
{
|
|
byte contentLinkType = x.ContentLinkType;
|
|
bool flag2 = ((contentLinkType == 1 || contentLinkType == 5) ? true : false);
|
|
flag = flag2;
|
|
}
|
|
return flag && x.ContentType.RowId != 6;
|
|
})
|
|
select new ContentFinderConditionData(x, dataManager.Language)).ToImmutableDictionary((ContentFinderConditionData x) => x.ContentFinderConditionId, (ContentFinderConditionData x) => x);
|
|
_questBattlesToContentFinderCondition = (from x in (from x in dataManager.GetExcelSheet<Quest>()
|
|
where x.RowId != 0 && x.IssuerLocation.RowId != 0
|
|
select x).SelectMany(GetQuestBattles)
|
|
select (QuestId: x.QuestId, Index: x.Index, CfcId: LookupContentFinderConditionForQuestBattle(dataManager, x.QuestBattleId))).ToImmutableDictionary<(ElementId, byte, uint), (ElementId, byte), uint>(((ElementId QuestId, byte Index, uint CfcId) x) => (QuestId: x.QuestId, Index: x.Index), ((ElementId QuestId, byte Index, uint CfcId) x) => x.CfcId);
|
|
}
|
|
|
|
public string? GetName(ushort territoryId)
|
|
{
|
|
return _territoryNames.GetValueOrDefault(territoryId);
|
|
}
|
|
|
|
public string GetNameAndId(ushort territoryId)
|
|
{
|
|
string name = GetName(territoryId);
|
|
if (name != null)
|
|
{
|
|
IFormatProvider invariantCulture = CultureInfo.InvariantCulture;
|
|
DefaultInterpolatedStringHandler handler = new DefaultInterpolatedStringHandler(3, 2, invariantCulture);
|
|
handler.AppendFormatted(name);
|
|
handler.AppendLiteral(" (");
|
|
handler.AppendFormatted(territoryId);
|
|
handler.AppendLiteral(")");
|
|
return string.Create(invariantCulture, ref handler);
|
|
}
|
|
return territoryId.ToString(CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public bool CanUseMount(ushort territoryId)
|
|
{
|
|
return _territoriesWithMount.Contains(territoryId);
|
|
}
|
|
|
|
public bool IsDutyInstance(ushort territoryId)
|
|
{
|
|
return _dutyTerritories.ContainsKey(territoryId);
|
|
}
|
|
|
|
public bool IsQuestBattleInstance(ushort territoryId)
|
|
{
|
|
if (_dutyTerritories.TryGetValue(territoryId, out var value))
|
|
{
|
|
return value == 7;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public string? GetInstanceName(ushort instanceId)
|
|
{
|
|
return _instanceNames.GetValueOrDefault(instanceId);
|
|
}
|
|
|
|
public ContentFinderConditionData? GetContentFinderCondition(uint cfcId)
|
|
{
|
|
return _contentFinderConditions.GetValueOrDefault(cfcId);
|
|
}
|
|
|
|
public bool TryGetContentFinderCondition(uint cfcId, [NotNullWhen(true)] out ContentFinderConditionData? contentFinderConditionData)
|
|
{
|
|
return _contentFinderConditions.TryGetValue(cfcId, out contentFinderConditionData);
|
|
}
|
|
|
|
public bool TryGetContentFinderConditionForSoloInstance(ElementId questId, byte index, [NotNullWhen(true)] out ContentFinderConditionData? contentFinderConditionData)
|
|
{
|
|
if (_questBattlesToContentFinderCondition.TryGetValue((questId, index), out var value))
|
|
{
|
|
return _contentFinderConditions.TryGetValue(value, out contentFinderConditionData);
|
|
}
|
|
contentFinderConditionData = null;
|
|
return false;
|
|
}
|
|
|
|
public IEnumerable<(ElementId QuestId, byte Index, ContentFinderConditionData Data)> GetAllQuestsWithQuestBattles()
|
|
{
|
|
return _questBattlesToContentFinderCondition.Select<KeyValuePair<(ElementId, byte), uint>, (ElementId, byte, ContentFinderConditionData)>((KeyValuePair<(ElementId QuestId, byte Index), uint> x) => (QuestId: x.Key.QuestId, Index: x.Key.Index, _contentFinderConditions[x.Value]));
|
|
}
|
|
|
|
private static string FixName(string name, ClientLanguage language)
|
|
{
|
|
if (string.IsNullOrEmpty(name) || language != ClientLanguage.English)
|
|
{
|
|
return name;
|
|
}
|
|
return string.Concat(name[0].ToString().ToUpper(CultureInfo.InvariantCulture), name.AsSpan(1));
|
|
}
|
|
|
|
private static IEnumerable<(ElementId QuestId, byte Index, uint QuestBattleId)> GetQuestBattles(Quest quest)
|
|
{
|
|
foreach (Quest.QuestParamsStruct questParam in quest.QuestParams)
|
|
{
|
|
if (questParam.ScriptInstruction == "QUESTBATTLE0")
|
|
{
|
|
yield return (QuestId: QuestId.FromRowId(quest.RowId), Index: 0, QuestBattleId: questParam.ScriptArg);
|
|
}
|
|
else if (questParam.ScriptInstruction == "QUESTBATTLE1")
|
|
{
|
|
yield return (QuestId: QuestId.FromRowId(quest.RowId), Index: 1, QuestBattleId: questParam.ScriptArg);
|
|
}
|
|
else if (questParam.ScriptInstruction.IsEmpty)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static uint LookupContentFinderConditionForQuestBattle(IDataManager dataManager, uint questBattleId)
|
|
{
|
|
if (questBattleId >= 5000)
|
|
{
|
|
return dataManager.GetExcelSheet<InstanceContent>().GetRow(questBattleId).ContentFinderCondition.RowId;
|
|
}
|
|
return dataManager.GetExcelSheet<QuestBattleResident>().GetRow(questBattleId).Unknown0;
|
|
}
|
|
}
|