qstbak/Questionable/Questionable.Data/TerritoryData.cs
2025-10-09 07:47:19 +10:00

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;
}
}