"type": "boolean",
"default": true
},
+ "ExtraQuestItems": {
+ "description": "Some quests (such as Ixal) add quest items to gathering nodes, but there's no clear connection between the item and the node in the sheets",
+ "type": "array",
+ "items": {
+ "type": "integer",
+ "minimum": 2000000
+ }
+ },
"Groups": {
"type": "array",
"items": {
Assignment(nameof(GatheringRoot.FlyBetweenNodes), root.FlyBetweenNodes,
emptyRoot.FlyBetweenNodes)
.AsSyntaxNodeOrToken(),
+ AssignmentList(nameof(GatheringRoot.ExtraQuestItems), root.ExtraQuestItems).AsSyntaxNodeOrToken(),
AssignmentList(nameof(GatheringRoot.Groups), root.Groups).AsSyntaxNodeOrToken()))));
}
catch (Exception e)
public List<QuestStep> Steps { get; set; } = [];
public bool? FlyBetweenNodes { get; set; }
+ public List<uint> ExtraQuestItems { get; set; } = [];
public List<GatheringNodeGroup> Groups { get; set; } = [];
}
{
private readonly IContextMenu _contextMenu;
private readonly QuestController _questController;
+ private readonly GatheringPointRegistry _gatheringPointRegistry;
private readonly GatheringData _gatheringData;
private readonly QuestRegistry _questRegistry;
private readonly QuestData _questData;
public ContextMenuController(
IContextMenu contextMenu,
QuestController questController,
+ GatheringPointRegistry gatheringPointRegistry,
GatheringData gatheringData,
QuestRegistry questRegistry,
QuestData questData,
{
_contextMenu = contextMenu;
_questController = questController;
+ _gatheringPointRegistry = gatheringPointRegistry;
_gatheringData = gatheringData;
_questRegistry = questRegistry;
_questData = questData;
if (classJob != currentClassJob && currentClassJob is EClassJob.Miner or EClassJob.Botanist)
return;
- if (!_gatheringData.TryGetGatheringPointId(itemId, classJob, out _))
+ if (!_gatheringPointRegistry.TryGetGatheringPointId(itemId, classJob, out _))
{
_logger.LogInformation("No gathering point found for {ClassJob}.", classJob);
return;
private readonly AetheryteFunctions _aetheryteFunctions;
private readonly ExcelFunctions _excelFunctions;
private readonly QuestController _questController;
- private readonly GatheringData _gatheringData;
private readonly GatheringPointRegistry _gatheringPointRegistry;
private readonly QuestRegistry _questRegistry;
private readonly QuestData _questData;
AetheryteFunctions aetheryteFunctions,
ExcelFunctions excelFunctions,
QuestController questController,
- GatheringData gatheringData,
GatheringPointRegistry gatheringPointRegistry,
QuestRegistry questRegistry,
QuestData questData,
_aetheryteFunctions = aetheryteFunctions;
_excelFunctions = excelFunctions;
_questController = questController;
- _gatheringData = gatheringData;
_gatheringPointRegistry = gatheringPointRegistry;
_questRegistry = questRegistry;
_questData = questData;
if (step != null && (step.TerritoryId != _clientState.TerritoryType || step.TargetTerritoryId == null) &&
step.InteractionType == EInteractionType.Gather)
{
- if (_gatheringData.TryGetGatheringPointId(step.ItemsToGather[0].ItemId,
+ if (_gatheringPointRegistry.TryGetGatheringPointId(step.ItemsToGather[0].ItemId,
(EClassJob?)_clientState.LocalPlayer?.ClassJob.RowId ?? EClassJob.Adventurer,
out GatheringPointId? gatheringPointId) &&
_gatheringPointRegistry.TryGetGatheringPoint(gatheringPointId, out GatheringRoot? root))
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
+using System.Linq;
using System.Text.Json;
using Dalamud.Plugin;
+using LLib.GameData;
using Microsoft.Extensions.Logging;
+using Questionable.Data;
using Questionable.GatheringPaths;
using Questionable.Model;
using Questionable.Model.Gathering;
{
private readonly IDalamudPluginInterface _pluginInterface;
private readonly QuestRegistry _questRegistry;
+ private readonly GatheringData _gatheringData;
private readonly ILogger<QuestRegistry> _logger;
private readonly Dictionary<GatheringPointId, GatheringRoot> _gatheringPoints = new();
- public GatheringPointRegistry(IDalamudPluginInterface pluginInterface, QuestRegistry questRegistry,
+ public GatheringPointRegistry(IDalamudPluginInterface pluginInterface,
+ QuestRegistry questRegistry,
+ GatheringData gatheringData,
ILogger<QuestRegistry> logger)
{
_pluginInterface = pluginInterface;
_questRegistry = questRegistry;
+ _gatheringData = gatheringData;
_logger = logger;
_questRegistry.Reloaded += OnReloaded;
public bool TryGetGatheringPoint(GatheringPointId gatheringPointId, [NotNullWhen(true)] out GatheringRoot? gatheringRoot)
=> _gatheringPoints.TryGetValue(gatheringPointId, out gatheringRoot);
+ public bool TryGetGatheringPointId(uint itemId, EClassJob classJobId,
+ [NotNullWhen(true)] out GatheringPointId? gatheringPointId)
+ {
+ if (classJobId == EClassJob.Miner)
+ {
+ if (_gatheringData.TryGetMinerGatheringPointByItemId(itemId, out gatheringPointId))
+ return true;
+
+ gatheringPointId = _gatheringPoints
+ .Where(x => x.Value.ExtraQuestItems.Contains(itemId))
+ .Select(x => x.Key)
+ .FirstOrDefault(x => _gatheringData.MinerGatheringPoints.Contains(x));
+ return gatheringPointId != null;
+ }
+ else if (classJobId == EClassJob.Botanist)
+ {
+ if (_gatheringData.TryGetBotanistGatheringPointByItemId(itemId, out gatheringPointId))
+ return true;
+
+ gatheringPointId = _gatheringPoints
+ .Where(x => x.Value.ExtraQuestItems.Contains(itemId))
+ .Select(x => x.Key)
+ .FirstOrDefault(x => _gatheringData.BotanistGatheringPoints.Contains(x));
+ return gatheringPointId != null;
+ }
+ else
+ {
+ gatheringPointId = null;
+ return false;
+ }
+ }
+
public void Dispose()
{
_questRegistry.Reloaded -= OnReloaded;
}
internal sealed class DelayedGatheringExecutor(
- GatheringData gatheringData,
GatheringPointRegistry gatheringPointRegistry,
TerritoryData territoryData,
IClientState clientState,
public IEnumerable<ITask> CreateExtraTasks()
{
EClassJob currentClassJob = (EClassJob)clientState.LocalPlayer!.ClassJob.RowId;
- if (!gatheringData.TryGetGatheringPointId(Task.GatheredItem.ItemId, currentClassJob,
+ if (!gatheringPointRegistry.TryGetGatheringPointId(Task.GatheredItem.ItemId, currentClassJob,
out GatheringPointId? gatheringPointId))
throw new TaskException($"No gathering point found for item {Task.GatheredItem.ItemId}");
.ToDictionary(x => x.ItemId, x => x.NpcId);
}
- public bool TryGetGatheringPointId(uint itemId, EClassJob classJobId,
- [NotNullWhen(true)] out GatheringPointId? gatheringPointId)
- {
- if (classJobId == EClassJob.Miner)
- return _minerGatheringPoints.TryGetValue(itemId, out gatheringPointId);
- else if (classJobId == EClassJob.Botanist)
- return _botanistGatheringPoints.TryGetValue(itemId, out gatheringPointId);
- else
- {
- gatheringPointId = null;
- return false;
- }
- }
+ public IEnumerable<GatheringPointId> MinerGatheringPoints => _minerGatheringPoints.Values;
+ public IEnumerable<GatheringPointId> BotanistGatheringPoints => _botanistGatheringPoints.Values;
+
+ public bool TryGetMinerGatheringPointByItemId(uint itemId, [NotNullWhen(true)] out GatheringPointId? gatheringPointId)
+ => _minerGatheringPoints.TryGetValue(itemId, out gatheringPointId);
+
+ public bool TryGetBotanistGatheringPointByItemId(uint itemId, [NotNullWhen(true)] out GatheringPointId? gatheringPointId)
+ => _botanistGatheringPoints.TryGetValue(itemId, out gatheringPointId);
public ushort GetRecommendedCollectability(uint itemId)
=> _itemIdToCollectability.GetValueOrDefault(itemId);