Migrate questIds to IId

This commit is contained in:
Liza 2024-08-03 20:30:18 +02:00
parent ee2b49f566
commit 36a0f72bd9
Signed by: liza
GPG Key ID: 7199F8D727D55F67
34 changed files with 349 additions and 201 deletions

View File

@ -162,6 +162,7 @@ public class QuestSourceGenerator : ISourceGenerator
SyntaxNodeList(
AssignmentList(nameof(QuestRoot.Author), quest.Author)
.AsSyntaxNodeOrToken(),
Assignment(nameof(QuestRoot.Disabled), quest.Disabled, false).AsSyntaxNodeOrToken(),
Assignment(nameof(QuestRoot.Comment), quest.Comment, null)
.AsSyntaxNodeOrToken(),
AssignmentList(nameof(QuestRoot.TerritoryBlacklist),
@ -304,7 +305,8 @@ public class QuestSourceGenerator : ISourceGenerator
Assignment(nameof(QuestStep.ContentFinderConditionId),
step.ContentFinderConditionId, emptyStep.ContentFinderConditionId)
.AsSyntaxNodeOrToken(),
Assignment(nameof(QuestStep.SkipConditions), step.SkipConditions, emptyStep.SkipConditions)
Assignment(nameof(QuestStep.SkipConditions), step.SkipConditions,
emptyStep.SkipConditions)
.AsSyntaxNodeOrToken(),
AssignmentList(nameof(QuestStep.RequiredQuestVariables),
step.RequiredQuestVariables)

View File

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Numerics;
using Microsoft.CodeAnalysis;
@ -57,6 +56,24 @@ public static class RoslynShortcuts
SyntaxKind.SimpleMemberAccessExpression,
IdentifierName(value.GetType().Name),
IdentifierName(value.GetType().GetEnumName(value)!));
else if (value is QuestId questId)
{
return ObjectCreationExpression(
IdentifierName(nameof(QuestId)))
.WithArgumentList(
ArgumentList(
SingletonSeparatedList(
Argument(LiteralValue(questId.Value)))));
}
else if (value is LeveId leveId)
{
return ObjectCreationExpression(
IdentifierName(nameof(LeveId)))
.WithArgumentList(
ArgumentList(
SingletonSeparatedList(
Argument(LiteralValue(leveId.Value)))));
}
else if (value is Vector3 vector)
{
return ObjectCreationExpression(

View File

@ -1,27 +0,0 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "liza",
"QuestSequence": [
{
"Sequence": 255,
"Steps": [
{
"Position": {
"X": -435.39066,
"Y": -9.809827,
"Z": -594.5472
},
"TerritoryId": 1187,
"InteractionType": "WalkTo",
"Fly": true,
"RequiredGatheredItems": [
{
"ItemId": 43992,
"ItemCount": 1234
}
]
}
]
}
]
}

View File

@ -39,8 +39,7 @@
"ItemId": 35848,
"ItemCount": 1
}
],
"NextQuestId": 4159
]
}
]
},

View File

@ -0,0 +1,19 @@
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Questionable.Model.Questing.Converter;
public class IdConverter : JsonConverter<IId>
{
public override IId Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
uint value = reader.GetUInt32();
return Id.From(value);
}
public override void Write(Utf8JsonWriter writer, IId value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}

View File

@ -0,0 +1,58 @@
using System;
using System.Globalization;
namespace Questionable.Model.Questing
{
public interface IId : IComparable<IId>
{
public ushort Value { get; }
}
public static class Id
{
public static IId From(uint value)
{
if (value >= 100_000 && value < 200_000)
return new LeveId((ushort)(value - 100_000));
else
return new QuestId((ushort)value);
}
}
public sealed record QuestId(ushort Value) : IId
{
public override string ToString()
{
return "Q" + Value.ToString(CultureInfo.InvariantCulture);
}
public int CompareTo(IId? other)
{
if (ReferenceEquals(this, other)) return 0;
if (ReferenceEquals(null, other)) return 1;
return Value.CompareTo(other.Value);
}
}
public sealed record LeveId(ushort Value) : IId
{
public override string ToString()
{
return "L" + Value.ToString(CultureInfo.InvariantCulture);
}
public int CompareTo(IId? other)
{
if (ReferenceEquals(this, other)) return 0;
if (ReferenceEquals(null, other)) return 1;
return Value.CompareTo(other.Value);
}
}
}
namespace System.Runtime.CompilerServices
{
internal static class IsExternalInit
{
}
}

View File

@ -72,10 +72,14 @@ public sealed class QuestStep
public IList<uint> PointMenuChoices { get; set; } = new List<uint>();
// TODO: Not implemented
public ushort? PickUpQuestId { get; set; }
[JsonConverter(typeof(IdConverter))]
public IId? PickUpQuestId { get; set; }
public ushort? TurnInQuestId { get; set; }
public ushort? NextQuestId { get; set; }
[JsonConverter(typeof(IdConverter))]
public IId? TurnInQuestId { get; set; }
[JsonConverter(typeof(IdConverter))]
public IId? NextQuestId { get; set; }
[JsonConstructor]
public QuestStep()

View File

@ -13,8 +13,8 @@ public sealed class SkipStepConditions
public List<ushort> InTerritory { get; set; } = new();
public List<ushort> NotInTerritory { get; set; } = new();
public SkipItemConditions? Item { get; set; }
public List<ushort> QuestsAccepted { get; set; } = new();
public List<ushort> QuestsCompleted { get; set; } = new();
public List<IId> QuestsAccepted { get; set; } = new();
public List<IId> QuestsCompleted { get; set; } = new();
public EExtraSkipCondition? ExtraCondition { get; set; }
public bool HasSkipConditions()

View File

@ -168,9 +168,9 @@ internal sealed class CombatController : IDisposable
}
}
if (QuestWorkUtils.HasCompletionFlags(condition.CompletionQuestVariablesFlags))
if (QuestWorkUtils.HasCompletionFlags(condition.CompletionQuestVariablesFlags) && _currentFight.Data.QuestId is QuestId questId)
{
var questWork = _gameFunctions.GetQuestEx(_currentFight.Data.QuestId);
var questWork = _gameFunctions.GetQuestEx(questId);
if (questWork != null && QuestWorkUtils.MatchesQuestWork(condition.CompletionQuestVariablesFlags,
questWork.Value))
{
@ -303,7 +303,7 @@ internal sealed class CombatController : IDisposable
public sealed class CombatData
{
public required ushort QuestId { get; init; }
public required IId QuestId { get; init; }
public required EEnemySpawnType SpawnType { get; init; }
public required List<uint> KillEnemyDataIds { get; init; }
public required List<ComplexCombatData> ComplexCombatDatas { get; init; }

View File

@ -4,6 +4,7 @@ using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.Command;
using Dalamud.Plugin.Services;
using Questionable.Model;
using Questionable.Model.Questing;
using Questionable.Windows;
using Questionable.Windows.QuestComponents;
@ -127,11 +128,11 @@ internal sealed class CommandHandler : IDisposable
return;
}
if (arguments.Length >= 1 && ushort.TryParse(arguments[0], out ushort questId))
if (arguments.Length >= 1 && uint.TryParse(arguments[0], out uint questId))
{
if (_questRegistry.TryGetQuest(questId, out Quest? quest))
if (_questRegistry.TryGetQuest(Id.From(questId), out Quest? quest))
{
_debugOverlay.HighlightedQuest = questId;
_debugOverlay.HighlightedQuest = quest.QuestId;
_chatGui.Print($"[Questionable] Set highlighted quest to {questId} ({quest.Info.Name}).");
}
else
@ -146,11 +147,11 @@ internal sealed class CommandHandler : IDisposable
private void SetNextQuest(string[] arguments)
{
if (arguments.Length >= 1 && ushort.TryParse(arguments[0], out ushort questId))
if (arguments.Length >= 1 && uint.TryParse(arguments[0], out uint questId))
{
if (_gameFunctions.IsQuestLocked(questId, 0))
if (_gameFunctions.IsQuestLocked(Id.From(questId)))
_chatGui.PrintError($"[Questionable] Quest {questId} is locked.");
else if (_questRegistry.TryGetQuest(questId, out Quest? quest))
else if (_questRegistry.TryGetQuest(Id.From(questId), out Quest? quest))
{
_questController.SetNextQuest(quest);
_chatGui.Print($"[Questionable] Set next quest to {questId} ({quest.Info.Name}).");
@ -171,7 +172,7 @@ internal sealed class CommandHandler : IDisposable
{
if (arguments.Length >= 1 && ushort.TryParse(arguments[0], out ushort questId))
{
if (_questRegistry.TryGetQuest(questId, out Quest? quest))
if (_questRegistry.TryGetQuest(Id.From(questId), out Quest? quest))
{
_questController.SimulateQuest(quest);
_chatGui.Print($"[Questionable] Simulating quest {questId} ({quest.Info.Name}).");

View File

@ -600,7 +600,7 @@ internal sealed class GameUiController : IDisposable
private unsafe void UnendingCodexPostSetup(AddonEvent type, AddonArgs args)
{
if (_questController.StartedQuest?.Quest.QuestId == 4526)
if (_questController.StartedQuest?.Quest.QuestId.Value == 4526)
{
_logger.LogInformation("Closing Unending Codex");
AtkUnitBase* addon = (AtkUnitBase*)args.Addon;
@ -610,7 +610,7 @@ internal sealed class GameUiController : IDisposable
private unsafe void ContentsTutorialPostSetup(AddonEvent type, AddonArgs args)
{
if (_questController.StartedQuest?.Quest.QuestId == 245)
if (_questController.StartedQuest?.Quest.QuestId.Value == 245)
{
_logger.LogInformation("Closing ContentsTutorial");
AtkUnitBase* addon = (AtkUnitBase*)args.Addon;
@ -623,7 +623,7 @@ internal sealed class GameUiController : IDisposable
/// </summary>
private unsafe void MultipleHelpWindowPostSetup(AddonEvent type, AddonArgs args)
{
if (_questController.StartedQuest?.Quest.QuestId == 245)
if (_questController.StartedQuest?.Quest.QuestId.Value == 245)
{
_logger.LogInformation("Closing MultipleHelpWindow");
AtkUnitBase* addon = (AtkUnitBase*)args.Addon;

View File

@ -209,8 +209,8 @@ internal sealed class QuestController : MiniTaskController<QuestController>
}
else
{
(ushort currentQuestId, currentSequence) = _gameFunctions.GetCurrentQuest();
if (currentQuestId == 0)
(IId? currentQuestId, currentSequence) = _gameFunctions.GetCurrentQuest();
if (currentQuestId == null || currentQuestId.Value == 0)
{
if (_startedQuest != null)
{
@ -330,7 +330,7 @@ internal sealed class QuestController : MiniTaskController<QuestController>
return (seq, seq.Steps[CurrentQuest.Step]);
}
public void IncreaseStepCount(ushort? questId, int? sequence, bool shouldContinue = false)
public void IncreaseStepCount(IId? questId, int? sequence, bool shouldContinue = false)
{
lock (_progressLock)
{
@ -545,7 +545,7 @@ internal sealed class QuestController : MiniTaskController<QuestController>
}
}
public void Skip(ushort questQuestId, byte currentQuestSequence)
public void Skip(IId questQuestId, byte currentQuestSequence)
{
lock (_progressLock)
{
@ -609,8 +609,9 @@ internal sealed class QuestController : MiniTaskController<QuestController>
1158, // Titan (Hard)
];
foreach (var questId in priorityQuests)
foreach (var id in priorityQuests)
{
var questId = new QuestId(id);
if (_gameFunctions.IsReadyToAcceptQuest(questId) && _questRegistry.TryGetQuest(questId, out var quest))
{
SetNextQuest(quest);

View File

@ -28,7 +28,7 @@ internal sealed class QuestRegistry
private readonly ILogger<QuestRegistry> _logger;
private readonly ICallGateProvider<object> _reloadDataIpc;
private readonly Dictionary<ushort, Quest> _quests = new();
private readonly Dictionary<IId, Quest> _quests = new();
public QuestRegistry(IDalamudPluginInterface pluginInterface, QuestData questData,
QuestValidator questValidator, JsonSchemaValidator jsonSchemaValidator,
@ -91,12 +91,12 @@ internal sealed class QuestRegistry
{
Quest quest = new()
{
QuestId = questId,
QuestId = new QuestId(questId),
Root = questRoot,
Info = _questData.GetQuestInfo(questId),
Info = _questData.GetQuestInfo(new QuestId(questId)),
ReadOnly = true,
};
_quests[questId] = quest;
_quests[quest.QuestId] = quest;
}
_logger.LogInformation("Loaded {Count} quests from assembly", _quests.Count);
@ -136,21 +136,21 @@ internal sealed class QuestRegistry
private void LoadQuestFromStream(string fileName, Stream stream)
{
_logger.LogTrace("Loading quest from '{FileName}'", fileName);
ushort? questId = ExtractQuestIdFromName(fileName);
IId? questId = ExtractQuestIdFromName(fileName);
if (questId == null)
return;
var questNode = JsonNode.Parse(stream)!;
_jsonSchemaValidator.Enqueue(questId.Value, questNode);
_jsonSchemaValidator.Enqueue(questId, questNode);
Quest quest = new Quest
{
QuestId = questId.Value,
QuestId = questId,
Root = questNode.Deserialize<QuestRoot>()!,
Info = _questData.GetQuestInfo(questId.Value),
Info = _questData.GetQuestInfo(questId),
ReadOnly = false,
};
_quests[questId.Value] = quest;
_quests[quest.QuestId] = quest;
}
private void LoadFromDirectory(DirectoryInfo directory, LogLevel logLevel = LogLevel.Information)
@ -179,7 +179,7 @@ internal sealed class QuestRegistry
LoadFromDirectory(childDirectory, logLevel);
}
private static ushort? ExtractQuestIdFromName(string resourceName)
private static IId? ExtractQuestIdFromName(string resourceName)
{
string name = resourceName.Substring(0, resourceName.Length - ".json".Length);
name = name.Substring(name.LastIndexOf('.') + 1);
@ -188,11 +188,30 @@ internal sealed class QuestRegistry
return null;
string[] parts = name.Split('_', 2);
return ushort.Parse(parts[0], CultureInfo.InvariantCulture);
return Id.From(uint.Parse(parts[0], CultureInfo.InvariantCulture));
}
public bool IsKnownQuest(ushort questId) => _quests.ContainsKey(questId);
public bool IsKnownQuest(IId id)
{
if (id is QuestId questId)
return IsKnownQuest(questId);
else
return false;
}
public bool TryGetQuest(ushort questId, [NotNullWhen(true)] out Quest? quest)
public bool IsKnownQuest(QuestId questId) => _quests.ContainsKey(questId);
public bool TryGetQuest(IId id, [NotNullWhen(true)] out Quest? quest)
{
if (id is QuestId questId)
return TryGetQuest(questId, out quest);
else
{
quest = null;
return false;
}
}
public bool TryGetQuest(QuestId questId, [NotNullWhen(true)] out Quest? quest)
=> _quests.TryGetValue(questId, out quest);
}

View File

@ -18,20 +18,20 @@ internal static class NextQuest
if (step.NextQuestId == null)
return null;
if (step.NextQuestId.Value == quest.QuestId)
if (step.NextQuestId == quest.QuestId)
return null;
return serviceProvider.GetRequiredService<SetQuest>()
.With(step.NextQuestId.Value, quest.QuestId);
.With(step.NextQuestId, quest.QuestId);
}
}
internal sealed class SetQuest(QuestRegistry questRegistry, QuestController questController, GameFunctions gameFunctions, ILogger<SetQuest> logger) : ITask
{
public ushort NextQuestId { get; set; }
public ushort CurrentQuestId { get; set; }
public IId NextQuestId { get; set; } = null!;
public IId CurrentQuestId { get; set; } = null!;
public ITask With(ushort nextQuestId, ushort currentQuestId)
public ITask With(IId nextQuestId, IId currentQuestId)
{
NextQuestId = nextQuestId;
CurrentQuestId = currentQuestId;

View File

@ -1,7 +1,9 @@
namespace Questionable.Controller.Steps;
using Questionable.Model.Questing;
namespace Questionable.Controller.Steps;
internal interface ILastTask : ITask
{
public ushort QuestId { get; }
public IId QuestId { get; }
public int Sequence { get; }
}

View File

@ -84,7 +84,7 @@ internal static class Combat
private CombatController.CombatData _combatData = null!;
private IList<QuestWorkValue?> _completionQuestVariableFlags = null!;
public ITask With(ushort questId, bool isLastStep, EEnemySpawnType enemySpawnType, IList<uint> killEnemyDataIds,
public ITask With(IId questId, bool isLastStep, EEnemySpawnType enemySpawnType, IList<uint> killEnemyDataIds,
IList<QuestWorkValue?> completionQuestVariablesFlags, IList<ComplexCombatData> complexCombatData)
{
_isLastStep = isLastStep;
@ -107,9 +107,9 @@ internal static class Combat
return ETaskResult.StillRunning;
// if our quest step has any completion flags, we need to check if they are set
if (QuestWorkUtils.HasCompletionFlags(_completionQuestVariableFlags))
if (QuestWorkUtils.HasCompletionFlags(_completionQuestVariableFlags) && _combatData.QuestId is QuestId questId)
{
var questWork = gameFunctions.GetQuestEx(_combatData.QuestId);
var questWork = gameFunctions.GetQuestEx(questId);
if (questWork == null)
return ETaskResult.StillRunning;

View File

@ -118,7 +118,7 @@ internal static class UseItem
private DateTime _continueAt;
private int _itemCount;
public ushort? QuestId { get; set; }
public IId? QuestId { get; set; }
public uint ItemId { get; set; }
public IList<QuestWorkValue?> CompletionQuestVariablesFlags { get; set; } = new List<QuestWorkValue?>();
public bool StartingCombat { get; set; }
@ -142,9 +142,9 @@ internal static class UseItem
public unsafe ETaskResult Update()
{
if (QuestId.HasValue && QuestWorkUtils.HasCompletionFlags(CompletionQuestVariablesFlags))
if (QuestId is QuestId questId && QuestWorkUtils.HasCompletionFlags(CompletionQuestVariablesFlags))
{
QuestWork? questWork = gameFunctions.GetQuestEx(QuestId.Value);
QuestWork? questWork = gameFunctions.GetQuestEx(questId);
if (questWork != null &&
QuestWorkUtils.MatchesQuestWork(CompletionQuestVariablesFlags, questWork.Value))
return ETaskResult.TaskComplete;
@ -203,7 +203,7 @@ internal static class UseItem
public uint DataId { get; set; }
public ITask With(ushort? questId, uint dataId, uint itemId, IList<QuestWorkValue?> completionQuestVariablesFlags)
public ITask With(IId? questId, uint dataId, uint itemId, IList<QuestWorkValue?> completionQuestVariablesFlags)
{
QuestId = questId;
DataId = dataId;
@ -227,7 +227,7 @@ internal static class UseItem
public Vector3 Position { get; set; }
public ITask With(ushort? questId, Vector3 position, uint itemId, IList<QuestWorkValue?> completionQuestVariablesFlags)
public ITask With(IId? questId, Vector3 position, uint itemId, IList<QuestWorkValue?> completionQuestVariablesFlags)
{
QuestId = questId;
Position = position;
@ -249,7 +249,7 @@ internal static class UseItem
public uint DataId { get; set; }
public ITask With(ushort? questId, uint dataId, uint itemId, IList<QuestWorkValue?> completionQuestVariablesFlags,
public ITask With(IId? questId, uint dataId, uint itemId, IList<QuestWorkValue?> completionQuestVariablesFlags,
bool startingCombat = false)
{
QuestId = questId;
@ -270,7 +270,7 @@ internal static class UseItem
{
private readonly GameFunctions _gameFunctions = gameFunctions;
public ITask With(ushort? questId, uint itemId, IList<QuestWorkValue?> completionQuestVariablesFlags)
public ITask With(IId? questId, uint itemId, IList<QuestWorkValue?> completionQuestVariablesFlags)
{
QuestId = questId;
ItemId = itemId;

View File

@ -45,9 +45,9 @@ internal static class SkipCondition
{
public QuestStep Step { get; set; } = null!;
public SkipStepConditions SkipConditions { get; set; } = null!;
public ushort QuestId { get; set; }
public IId QuestId { get; set; } = null!;
public ITask With(QuestStep step, SkipStepConditions skipConditions, ushort questId)
public ITask With(QuestStep step, SkipStepConditions skipConditions, IId questId)
{
Step = step;
SkipConditions = skipConditions;
@ -156,32 +156,35 @@ internal static class SkipCondition
return true;
}
QuestWork? questWork = gameFunctions.GetQuestEx(QuestId);
if (QuestWorkUtils.HasCompletionFlags(Step.CompletionQuestVariablesFlags) && questWork != null)
if (QuestId is QuestId questId)
{
if (QuestWorkUtils.MatchesQuestWork(Step.CompletionQuestVariablesFlags, questWork.Value))
QuestWork? questWork = gameFunctions.GetQuestEx(questId);
if (QuestWorkUtils.HasCompletionFlags(Step.CompletionQuestVariablesFlags) && questWork != null)
{
logger.LogInformation("Skipping step, as quest variables match (step is complete)");
return true;
if (QuestWorkUtils.MatchesQuestWork(Step.CompletionQuestVariablesFlags, questWork.Value))
{
logger.LogInformation("Skipping step, as quest variables match (step is complete)");
return true;
}
}
}
if (Step is { SkipConditions.StepIf: { } conditions } && questWork != null)
{
if (QuestWorkUtils.MatchesQuestWork(conditions.CompletionQuestVariablesFlags, questWork.Value))
if (Step is { SkipConditions.StepIf: { } conditions } && questWork != null)
{
logger.LogInformation("Skipping step, as quest variables match (step can be skipped)");
return true;
if (QuestWorkUtils.MatchesQuestWork(conditions.CompletionQuestVariablesFlags, questWork.Value))
{
logger.LogInformation("Skipping step, as quest variables match (step can be skipped)");
return true;
}
}
}
if (Step is { RequiredQuestVariables: { } requiredQuestVariables } && questWork != null)
{
if (!QuestWorkUtils.MatchesRequiredQuestWorkConfig(requiredQuestVariables, questWork.Value,
logger))
if (Step is { RequiredQuestVariables: { } requiredQuestVariables } && questWork != null)
{
logger.LogInformation("Skipping step, as required variables do not match");
return true;
if (!QuestWorkUtils.MatchesRequiredQuestWorkConfig(requiredQuestVariables, questWork.Value,
logger))
{
logger.LogInformation("Skipping step, as required variables do not match");
return true;
}
}
}
@ -195,13 +198,13 @@ internal static class SkipCondition
}
}
if (Step.PickUpQuestId != null && gameFunctions.IsQuestAcceptedOrComplete(Step.PickUpQuestId.Value))
if (Step.PickUpQuestId != null && gameFunctions.IsQuestAcceptedOrComplete(Step.PickUpQuestId))
{
logger.LogInformation("Skipping step, as we have already picked up the relevant quest");
return true;
}
if (Step.TurnInQuestId != null && gameFunctions.IsQuestComplete(Step.TurnInQuestId.Value))
if (Step.TurnInQuestId != null && gameFunctions.IsQuestComplete(Step.TurnInQuestId))
{
logger.LogInformation("Skipping step, as we have already completed the relevant quest");
return true;

View File

@ -30,7 +30,7 @@ internal static class WaitAtEnd
if (step.CompletionQuestVariablesFlags.Count == 6 && QuestWorkUtils.HasCompletionFlags(step.CompletionQuestVariablesFlags))
{
var task = serviceProvider.GetRequiredService<WaitForCompletionFlags>()
.With(quest, step);
.With((QuestId)quest.QuestId, step);
var delay = serviceProvider.GetRequiredService<WaitDelay>();
return [task, delay, Next(quest, sequence)];
}
@ -162,11 +162,11 @@ internal static class WaitAtEnd
internal sealed class WaitForCompletionFlags(GameFunctions gameFunctions) : ITask
{
public Quest Quest { get; set; } = null!;
public QuestId Quest { get; set; } = null!;
public QuestStep Step { get; set; } = null!;
public IList<QuestWorkValue?> Flags { get; set; } = null!;
public ITask With(Quest quest, QuestStep step)
public ITask With(QuestId quest, QuestStep step)
{
Quest = quest;
Step = step;
@ -178,7 +178,7 @@ internal static class WaitAtEnd
public ETaskResult Update()
{
QuestWork? questWork = gameFunctions.GetQuestEx(Quest.QuestId);
QuestWork? questWork = gameFunctions.GetQuestEx(Quest);
return questWork != null &&
QuestWorkUtils.MatchesQuestWork(Step.CompletionQuestVariablesFlags, questWork.Value)
? ETaskResult.TaskComplete
@ -214,11 +214,11 @@ internal static class WaitAtEnd
$"WaitObj({DataId} at {Destination.ToString("G", CultureInfo.InvariantCulture)} < {Distance})";
}
internal sealed class WaitQuestAccepted : ITask
internal sealed class WaitQuestAccepted(GameFunctions gameFunctions) : ITask
{
public ushort QuestId { get; set; }
public IId QuestId { get; set; } = null!;
public ITask With(ushort questId)
public ITask With(IId questId)
{
QuestId = questId;
return this;
@ -228,23 +228,19 @@ internal static class WaitAtEnd
public ETaskResult Update()
{
unsafe
{
var questManager = QuestManager.Instance();
return questManager != null && questManager->IsQuestAccepted(QuestId)
? ETaskResult.TaskComplete
: ETaskResult.StillRunning;
}
return gameFunctions.IsQuestAccepted(QuestId)
? ETaskResult.TaskComplete
: ETaskResult.StillRunning;
}
public override string ToString() => $"WaitQuestAccepted({QuestId})";
}
internal sealed class WaitQuestCompleted : ITask
internal sealed class WaitQuestCompleted(GameFunctions gameFunctions) : ITask
{
public ushort QuestId { get; set; }
public IId QuestId { get; set; } = null!;
public ITask With(ushort questId)
public ITask With(IId questId)
{
QuestId = questId;
return this;
@ -254,15 +250,15 @@ internal static class WaitAtEnd
public ETaskResult Update()
{
return QuestManager.IsQuestComplete(QuestId) ? ETaskResult.TaskComplete : ETaskResult.StillRunning;
return gameFunctions.IsQuestComplete(QuestId) ? ETaskResult.TaskComplete : ETaskResult.StillRunning;
}
public override string ToString() => $"WaitQuestComplete({QuestId})";
}
internal sealed class NextStep(ushort questId, int sequence) : ILastTask
internal sealed class NextStep(IId questId, int sequence) : ILastTask
{
public ushort QuestId { get; } = questId;
public IId QuestId { get; } = questId;
public int Sequence { get; } = sequence;
public bool Start() => true;
@ -274,7 +270,7 @@ internal static class WaitAtEnd
internal sealed class EndAutomation : ILastTask
{
public ushort QuestId => throw new InvalidOperationException();
public IId QuestId => throw new InvalidOperationException();
public int Sequence => throw new InvalidOperationException();
public bool Start() => true;

View File

@ -3,6 +3,7 @@ using System.Linq;
using Dalamud.Plugin.Services;
using Lumina.Excel.GeneratedSheets;
using Questionable.Model;
using Questionable.Model.Questing;
namespace Questionable.Data;
@ -21,15 +22,17 @@ internal sealed class JournalData
var genreLimsa = new Genre(uint.MaxValue - 3, "Starting in Limsa Lominsa", 1,
new uint[] { 108, 109 }.Concat(limsaStart.Quest.Select(x => x.Row))
.Where(x => x != 0)
.Select(x => questData.GetQuestInfo((ushort)(x & 0xFFFF))).ToList());
.Select(x => questData.GetQuestInfo(new QuestId((ushort)(x & 0xFFFF))))
.ToList());
var genreGridania = new Genre(uint.MaxValue - 2, "Starting in Gridania", 1,
new uint[] { 85, 123, 124 }.Concat(gridaniaStart.Quest.Select(x => x.Row))
.Where(x => x != 0)
.Select(x => questData.GetQuestInfo((ushort)(x & 0xFFFF))).ToList());
.Select(x => questData.GetQuestInfo(new QuestId((ushort)(x & 0xFFFF))))
.ToList());
var genreUldah = new Genre(uint.MaxValue - 1, "Starting in Ul'dah", 1,
new uint[] { 568, 569, 570 }.Concat(uldahStart.Quest.Select(x => x.Row))
.Where(x => x != 0)
.Select(x => questData.GetQuestInfo((ushort)(x & 0xFFFF)))
.Select(x => questData.GetQuestInfo(new QuestId((ushort)(x & 0xFFFF))))
.ToList());
genres.InsertRange(0, [genreLimsa, genreGridania, genreUldah]);
genres.Single(x => x.Id == 1)

View File

@ -4,13 +4,14 @@ using System.Collections.Immutable;
using System.Linq;
using Dalamud.Plugin.Services;
using Questionable.Model;
using Questionable.Model.Questing;
using Quest = Lumina.Excel.GeneratedSheets.Quest;
namespace Questionable.Data;
internal sealed class QuestData
{
private readonly ImmutableDictionary<ushort, QuestInfo> _quests;
private readonly ImmutableDictionary<QuestId, QuestInfo> _quests;
public QuestData(IDataManager dataManager)
{
@ -22,7 +23,15 @@ internal sealed class QuestData
.ToImmutableDictionary(x => x.QuestId, x => x);
}
public QuestInfo GetQuestInfo(ushort questId)
public QuestInfo GetQuestInfo(IId id)
{
if (id is QuestId questId)
return GetQuestInfo(questId);
throw new ArgumentException("Invalid id", nameof(id));
}
public QuestInfo GetQuestInfo(QuestId questId)
{
return _quests[questId] ?? throw new ArgumentOutOfRangeException(nameof(questId));
}

View File

@ -89,37 +89,36 @@ internal sealed unsafe class GameFunctions
public DateTime ReturnRequestedAt { get; set; } = DateTime.MinValue;
public (ushort CurrentQuest, byte Sequence) GetCurrentQuest()
public (IId? CurrentQuest, byte Sequence) GetCurrentQuest()
{
var (currentQuest, sequence) = GetCurrentQuestInternal();
QuestManager* questManager = QuestManager.Instance();
PlayerState* playerState = PlayerState.Instance();
if (currentQuest == 0)
if (currentQuest == null || currentQuest.Value == 0)
{
if (_clientState.TerritoryType == 181) // Starting in Limsa
return (107, 0);
return (new QuestId(107), 0);
if (_clientState.TerritoryType == 182) // Starting in Ul'dah
return (594, 0);
return (new QuestId(594), 0);
if (_clientState.TerritoryType == 183) // Starting in Gridania
return (39, 0);
return (new QuestId(39), 0);
return default;
}
else if (currentQuest == 681)
else if (currentQuest.Value == 681)
{
// if we have already picked up the GC quest, just return the progress for it
if (questManager->IsQuestAccepted(currentQuest) || QuestManager.IsQuestComplete(currentQuest))
if (IsQuestAccepted(currentQuest) || IsQuestComplete(currentQuest))
return (currentQuest, sequence);
// The company you keep...
return _configuration.General.GrandCompany switch
{
GrandCompany.TwinAdder => (680, 0),
GrandCompany.Maelstrom => (681, 0),
GrandCompany.TwinAdder => (new QuestId(680), 0),
GrandCompany.Maelstrom => (new QuestId(681), 0),
_ => default
};
}
else if (currentQuest == 3856 && !playerState->IsMountUnlocked(1)) // we come in peace
else if (currentQuest.Value == 3856 && !playerState->IsMountUnlocked(1)) // we come in peace
{
ushort chocoboQuest = (GrandCompany)playerState->GrandCompany switch
{
@ -129,20 +128,20 @@ internal sealed unsafe class GameFunctions
};
if (chocoboQuest != 0 && !QuestManager.IsQuestComplete(chocoboQuest))
return (chocoboQuest, QuestManager.GetQuestSequence(chocoboQuest));
return (new QuestId(chocoboQuest), QuestManager.GetQuestSequence(chocoboQuest));
}
else if (currentQuest == 801)
else if (currentQuest.Value == 801)
{
// skeletons in her closet, finish 'broadening horizons' to unlock the white wolf gate
ushort broadeningHorizons = 802;
if (questManager->IsQuestAccepted(broadeningHorizons))
return (broadeningHorizons, QuestManager.GetQuestSequence(broadeningHorizons));
QuestId broadeningHorizons = new QuestId(802);
if (IsQuestAccepted(broadeningHorizons))
return (broadeningHorizons, QuestManager.GetQuestSequence(broadeningHorizons.Value));
}
return (currentQuest, sequence);
}
public (ushort CurrentQuest, byte Sequence) GetCurrentQuestInternal()
public (IId? CurrentQuest, byte Sequence) GetCurrentQuestInternal()
{
var questManager = QuestManager.Instance();
if (questManager != null)
@ -150,7 +149,7 @@ internal sealed unsafe class GameFunctions
// always prioritize accepting MSQ quests, to make sure we don't turn in one MSQ quest and then go off to do
// side quests until the end of time.
var msqQuest = GetMainScenarioQuest(questManager);
if (msqQuest.CurrentQuest != 0 && _questRegistry.IsKnownQuest(msqQuest.CurrentQuest))
if (msqQuest.CurrentQuest is { Value: not 0 } && _questRegistry.IsKnownQuest(msqQuest.CurrentQuest))
return msqQuest;
// Use the quests in the same order as they're shown in the to-do list, e.g. if the MSQ is the first item,
@ -159,7 +158,7 @@ internal sealed unsafe class GameFunctions
// If no quests are marked as 'priority', accepting a new quest adds it to the top of the list.
for (int i = questManager->TrackedQuests.Length - 1; i >= 0; --i)
{
ushort currentQuest;
IId currentQuest;
var trackedQuest = questManager->TrackedQuests[i];
switch (trackedQuest.QuestType)
{
@ -167,12 +166,12 @@ internal sealed unsafe class GameFunctions
continue;
case 1: // normal quest
currentQuest = questManager->NormalQuests[trackedQuest.Index].QuestId;
currentQuest = new QuestId(questManager->NormalQuests[trackedQuest.Index].QuestId);
break;
}
if (_questRegistry.IsKnownQuest(currentQuest))
return (currentQuest, QuestManager.GetQuestSequence(currentQuest));
return (currentQuest, QuestManager.GetQuestSequence(currentQuest.Value));
}
// if we know no quest of those currently in the to-do list, just do MSQ
@ -182,7 +181,7 @@ internal sealed unsafe class GameFunctions
return default;
}
private (ushort CurrentQuest, byte Sequence) GetMainScenarioQuest(QuestManager* questManager)
private (QuestId? CurrentQuest, byte Sequence) GetMainScenarioQuest(QuestManager* questManager)
{
if (QuestManager.IsQuestComplete(3759)) // Memories Rekindled
{
@ -202,7 +201,7 @@ internal sealed unsafe class GameFunctions
// redoHud+44 is chapter
// redoHud+46 is quest
ushort questId = MemoryHelper.Read<ushort>((nint)questRedoHud + 46);
return (questId, QuestManager.GetQuestSequence(questId));
return (new QuestId(questId), QuestManager.GetQuestSequence(questId));
}
}
}
@ -214,12 +213,12 @@ internal sealed unsafe class GameFunctions
if (scenarioTree->Data == null)
return default;
ushort currentQuest = scenarioTree->Data->CurrentScenarioQuest;
if (currentQuest == 0)
QuestId currentQuest = new QuestId(scenarioTree->Data->CurrentScenarioQuest);
if (currentQuest.Value == 0)
return default;
// if the MSQ is hidden, we generally ignore it
if (questManager->IsQuestAccepted(currentQuest) && questManager->GetQuestById(currentQuest)->IsHidden)
if (IsQuestAccepted(currentQuest) && questManager->GetQuestById(currentQuest.Value)->IsHidden)
return default;
// it can sometimes happen (although this isn't reliably reproducible) that the quest returned here
@ -234,16 +233,23 @@ internal sealed unsafe class GameFunctions
&& quest.Info.Level > currentLevel)
return default;
return (currentQuest, QuestManager.GetQuestSequence(currentQuest));
return (currentQuest, QuestManager.GetQuestSequence(currentQuest.Value));
}
public QuestWork? GetQuestEx(ushort questId)
public QuestWork? GetQuestEx(QuestId questId)
{
QuestWork* questWork = QuestManager.Instance()->GetQuestById(questId);
QuestWork* questWork = QuestManager.Instance()->GetQuestById(questId.Value);
return questWork != null ? *questWork : null;
}
public bool IsReadyToAcceptQuest(ushort questId)
public bool IsReadyToAcceptQuest(IId id)
{
if (id is QuestId questId)
return IsReadyToAcceptQuest(questId);
return false;
}
public bool IsReadyToAcceptQuest(QuestId questId)
{
_questRegistry.TryGetQuest(questId, out var quest);
if (quest is { Info.IsRepeatable: true })
@ -268,29 +274,50 @@ internal sealed unsafe class GameFunctions
return true;
}
public bool IsQuestAcceptedOrComplete(ushort questId)
public bool IsQuestAcceptedOrComplete(IId questId)
{
return IsQuestComplete(questId) || IsQuestAccepted(questId);
}
public bool IsQuestAccepted(ushort questId)
public bool IsQuestAccepted(IId id)
{
if (id is QuestId questId)
return IsQuestAccepted(questId);
return false;
}
public bool IsQuestAccepted(QuestId questId)
{
QuestManager* questManager = QuestManager.Instance();
return questManager->IsQuestAccepted(questId);
return questManager->IsQuestAccepted(questId.Value);
}
public bool IsQuestComplete(IId id)
{
if (id is QuestId questId)
return IsQuestComplete(questId);
return false;
}
[SuppressMessage("Performance", "CA1822")]
public bool IsQuestComplete(ushort questId)
public bool IsQuestComplete(QuestId questId)
{
return QuestManager.IsQuestComplete(questId);
return QuestManager.IsQuestComplete(questId.Value);
}
public bool IsQuestLocked(ushort questId, ushort? extraCompletedQuest = null)
public bool IsQuestLocked(IId id, IId? extraCompletedQuest = null)
{
if (id is QuestId questId)
return IsQuestLocked(questId, extraCompletedQuest);
return false;
}
public bool IsQuestLocked(QuestId questId, IId? extraCompletedQuest = null)
{
var questInfo = _questData.GetQuestInfo(questId);
if (questInfo.QuestLocks.Count > 0)
{
var completedQuests = questInfo.QuestLocks.Count(x => IsQuestComplete(x) || x == extraCompletedQuest);
var completedQuests = questInfo.QuestLocks.Count(x => IsQuestComplete(x) || x.Equals(extraCompletedQuest));
if (questInfo.QuestLockJoin == QuestInfo.QuestJoin.All && questInfo.QuestLocks.Count == completedQuests)
return true;
else if (questInfo.QuestLockJoin == QuestInfo.QuestJoin.AtLeastOne && completedQuests > 0)
@ -303,12 +330,12 @@ internal sealed unsafe class GameFunctions
return !HasCompletedPreviousQuests(questInfo, extraCompletedQuest) || !HasCompletedPreviousInstances(questInfo);
}
private bool HasCompletedPreviousQuests(QuestInfo questInfo, ushort? extraCompletedQuest)
private bool HasCompletedPreviousQuests(QuestInfo questInfo, IId? extraCompletedQuest)
{
if (questInfo.PreviousQuests.Count == 0)
return true;
var completedQuests = questInfo.PreviousQuests.Count(x => IsQuestComplete(x) || x == extraCompletedQuest);
var completedQuests = questInfo.PreviousQuests.Count(x => IsQuestComplete(x) || x.Equals(extraCompletedQuest));
if (questInfo.PreviousQuestJoin == QuestInfo.QuestJoin.All &&
questInfo.PreviousQuests.Count == completedQuests)
return true;
@ -388,7 +415,7 @@ internal sealed unsafe class GameFunctions
if (_configuration.Advanced.NeverFly)
return false;
if (IsQuestAccepted(3304) && _condition[ConditionFlag.Mounted])
if (IsQuestAccepted(new QuestId(3304)) && _condition[ConditionFlag.Mounted])
{
BattleChara* battleChara = (BattleChara*)(_clientState.LocalPlayer?.Address ?? 0);
if (battleChara != null && battleChara->Mount.MountId == 198) // special quest amaro, not the normal one
@ -680,7 +707,7 @@ internal sealed unsafe class GameFunctions
if (excelSheetName == null)
{
var questRow =
_dataManager.GetExcelSheet<Lumina.Excel.GeneratedSheets2.Quest>()!.GetRow((uint)currentQuest.QuestId +
_dataManager.GetExcelSheet<Lumina.Excel.GeneratedSheets2.Quest>()!.GetRow((uint)currentQuest.QuestId.Value +
0x10000);
if (questRow == null)
{
@ -688,7 +715,7 @@ internal sealed unsafe class GameFunctions
return null;
}
excelSheetName = $"quest/{(currentQuest.QuestId / 100):000}/{questRow.Id}";
excelSheetName = $"quest/{(currentQuest.QuestId.Value / 100):000}/{questRow.Id}";
}
var excelSheet = _dataManager.Excel.GetSheet<QuestDialogueText>(excelSheetName);

View File

@ -6,7 +6,7 @@ namespace Questionable.Model;
internal sealed class Quest
{
public required ushort QuestId { get; init; }
public required IId QuestId { get; init; }
public required QuestRoot Root { get; init; }
public required QuestInfo Info { get; init; }
public required bool ReadOnly { get; init; }

View File

@ -5,6 +5,7 @@ using System.Linq;
using Dalamud.Game.Text;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using JetBrains.Annotations;
using Questionable.Model.Questing;
using ExcelQuest = Lumina.Excel.GeneratedSheets.Quest;
namespace Questionable.Model;
@ -13,9 +14,9 @@ internal sealed class QuestInfo
{
public QuestInfo(ExcelQuest quest)
{
QuestId = (ushort)(quest.RowId & 0xFFFF);
QuestId = new QuestId((ushort)(quest.RowId & 0xFFFF));
string suffix = QuestId switch
string suffix = QuestId.Value switch
{
85 => " (Lancer)",
108 => " (Marauder)",
@ -34,9 +35,15 @@ internal sealed class QuestInfo
Level = quest.ClassJobLevel0;
IssuerDataId = quest.IssuerStart;
IsRepeatable = quest.IsRepeatable;
PreviousQuests = quest.PreviousQuest.Select(x => (ushort)(x.Row & 0xFFFF)).Where(x => x != 0).ToImmutableList();
PreviousQuests = quest.PreviousQuest
.Select(x => new QuestId((ushort)(x.Row & 0xFFFF)))
.Where(x => x.Value != 0)
.ToImmutableList();
PreviousQuestJoin = (QuestJoin)quest.PreviousQuestJoin;
QuestLocks = quest.QuestLock.Select(x => (ushort)(x.Row & 0xFFFFF)).Where(x => x != 0).ToImmutableList();
QuestLocks = quest.QuestLock
.Select(x => new QuestId((ushort)(x.Row & 0xFFFFF)))
.Where(x => x.Value != 0)
.ToImmutableList();
QuestLockJoin = (QuestJoin)quest.QuestLockJoin;
JournalGenre = quest.JournalGenre?.Row;
SortKey = quest.SortKey;
@ -49,14 +56,14 @@ internal sealed class QuestInfo
}
public ushort QuestId { get; }
public QuestId QuestId { get; }
public string Name { get; }
public ushort Level { get; }
public uint IssuerDataId { get; }
public bool IsRepeatable { get; }
public ImmutableList<ushort> PreviousQuests { get; }
public ImmutableList<QuestId> PreviousQuests { get; }
public QuestJoin PreviousQuestJoin { get; }
public ImmutableList<ushort> QuestLocks { get; }
public ImmutableList<QuestId> QuestLocks { get; }
public QuestJoin QuestLockJoin { get; }
public List<ushort> PreviousInstanceContent { get; }
public QuestJoin PreviousInstanceContentJoin { get; }

View File

@ -1,10 +1,11 @@
using Questionable.Model;
using Questionable.Model.Questing;
namespace Questionable.Validation;
internal sealed record ValidationIssue
{
public required ushort? QuestId { get; init; }
public required IId? QuestId { get; init; }
public required byte? Sequence { get; init; }
public required int? Step { get; init; }
public EBeastTribe BeastTribe { get; init; } = EBeastTribe.None;

View File

@ -23,7 +23,7 @@ internal sealed class AethernetShortcutValidator : IQuestValidator
.Cast<ValidationIssue>();
}
private ValidationIssue? Validate(ushort questId, int sequenceNo, int stepId, AethernetShortcut? aethernetShortcut)
private ValidationIssue? Validate(IId questId, int sequenceNo, int stepId, AethernetShortcut? aethernetShortcut)
{
if (aethernetShortcut == null)
return null;

View File

@ -4,13 +4,14 @@ using System.Globalization;
using System.Text.Json.Nodes;
using Json.Schema;
using Questionable.Model;
using Questionable.Model.Questing;
using Questionable.QuestPaths;
namespace Questionable.Validation.Validators;
internal sealed class JsonSchemaValidator : IQuestValidator
{
private readonly Dictionary<ushort, JsonNode> _questNodes = new();
private readonly Dictionary<IId, JsonNode> _questNodes = new();
private JsonSchema? _questSchema;
public JsonSchemaValidator()
@ -46,7 +47,7 @@ internal sealed class JsonSchemaValidator : IQuestValidator
}
}
public void Enqueue(ushort questId, JsonNode questNode) => _questNodes[questId] = questNode;
public void Enqueue(IId questId, JsonNode questNode) => _questNodes[questId] = questNode;
public void Reset() => _questNodes.Clear();
}

View File

@ -46,7 +46,7 @@ internal sealed class DebugOverlay : Window
IsOpen = true;
}
public ushort? HighlightedQuest { get; set; }
public IId? HighlightedQuest { get; set; }
public override bool DrawConditions() => _configuration.Advanced.DebugOverlay;
@ -93,7 +93,7 @@ internal sealed class DebugOverlay : Window
private void DrawHighlightedQuest()
{
if (HighlightedQuest == null || !_questRegistry.TryGetQuest(HighlightedQuest.Value, out var quest))
if (HighlightedQuest == null || !_questRegistry.TryGetQuest(HighlightedQuest, out var quest))
return;
foreach (var sequence in quest.Root.QuestSequence)

View File

@ -201,8 +201,7 @@ internal sealed class JournalProgressWindow : LWindow, IDisposable
if (ImGui.IsItemClicked() && _commandManager.Commands.TryGetValue("/questinfo", out var commandInfo))
{
_commandManager.DispatchCommand("/questinfo",
questInfo.QuestId.ToString(CultureInfo.InvariantCulture), commandInfo);
_commandManager.DispatchCommand("/questinfo", questInfo.QuestId.ToString(), commandInfo);
}
if (ImGui.IsItemHovered())

View File

@ -4,16 +4,19 @@ using Dalamud.Interface.Utility.Raii;
using FFXIVClientStructs.FFXIV.Client.Game.UI;
using FFXIVClientStructs.FFXIV.Common.Math;
using Questionable.Data;
using Questionable.Model.Questing;
namespace Questionable.Windows.QuestComponents;
internal sealed class ARealmRebornComponent
{
private const ushort ATimeForEveryPurpose = 425;
private const ushort TheUltimateWeapon = 524;
private const ushort GoodIntentions = 363;
private static readonly QuestId ATimeForEveryPurpose = new(425);
private static readonly QuestId TheUltimateWeapon = new(524);
private static readonly QuestId GoodIntentions = new(363);
private static readonly ushort[] RequiredPrimalInstances = [20004, 20006, 20005];
private static readonly ushort[] RequiredAllianceRaidQuests = [1709, 1200, 1201, 1202, 1203, 1474, 494, 495];
private static readonly QuestId[] RequiredAllianceRaidQuests =
[new(1709), new(1200), new(1201), new(1202), new(1203), new(1474), new(494), new(495)];
private readonly GameFunctions _gameFunctions;
private readonly QuestData _questData;

View File

@ -151,7 +151,10 @@ internal sealed class ActiveQuestComponent
private QuestWork? DrawQuestWork(QuestController.QuestProgress currentQuest)
{
var questWork = _gameFunctions.GetQuestEx(currentQuest.Quest.QuestId);
if (currentQuest.Quest.QuestId is not QuestId questId)
return null;
var questWork = _gameFunctions.GetQuestEx(questId);
if (questWork != null)
{
Vector4 color;
@ -271,7 +274,7 @@ internal sealed class ActiveQuestComponent
ImGui.SameLine();
if (ImGuiComponents.IconButton(FontAwesomeIcon.Atlas))
_commandManager.DispatchCommand("/questinfo",
currentQuest.Quest.QuestId.ToString(CultureInfo.InvariantCulture), commandInfo);
currentQuest.Quest.QuestId.ToString() ?? string.Empty, commandInfo);
}
bool autoAcceptNextQuest = _configuration.General.AutoAcceptNextQuest;

View File

@ -110,7 +110,7 @@ internal sealed class QuestSelectionWindow : LWindow
foreach (var unacceptedQuest in Map.Instance()->UnacceptedQuestMarkers)
{
ushort questId = (ushort)(unacceptedQuest.ObjectiveId & 0xFFFF);
QuestId questId = new QuestId((ushort)(unacceptedQuest.ObjectiveId & 0xFFFF));
if (_quests.All(q => q.QuestId != questId))
_quests.Add(_questData.GetQuestInfo(questId));
}
@ -161,7 +161,7 @@ internal sealed class QuestSelectionWindow : LWindow
{
ImGui.TableNextRow();
string questId = quest.QuestId.ToString(CultureInfo.InvariantCulture);
string questId = quest.QuestId.ToString();
bool isKnownQuest = _questRegistry.TryGetQuest(quest.QuestId, out var knownQuest);
if (ImGui.TableNextColumn())

View File

@ -56,11 +56,11 @@ internal sealed class QuestValidationWindow : LWindow
ImGui.TableNextRow();
if (ImGui.TableNextColumn())
ImGui.TextUnformatted(validationIssue.QuestId?.ToString(CultureInfo.InvariantCulture) ?? string.Empty);
ImGui.TextUnformatted(validationIssue.QuestId?.ToString() ?? string.Empty);
if (ImGui.TableNextColumn())
ImGui.TextUnformatted(validationIssue.QuestId != null
? _questData.GetQuestInfo(validationIssue.QuestId.Value).Name
? _questData.GetQuestInfo(validationIssue.QuestId).Name
: validationIssue.BeastTribe.ToString());
if (ImGui.TableNextColumn())

View File

@ -4,6 +4,7 @@ using Dalamud.Interface.Colors;
using Dalamud.Plugin;
using FFXIVClientStructs.FFXIV.Client.Game.UI;
using ImGuiNET;
using Questionable.Model.Questing;
namespace Questionable.Windows;
@ -18,7 +19,7 @@ internal sealed class UiUtils
_pluginInterface = pluginInterface;
}
public (Vector4 color, FontAwesomeIcon icon, string status) GetQuestStyle(ushort questId)
public (Vector4 color, FontAwesomeIcon icon, string status) GetQuestStyle(IId questId)
{
if (_gameFunctions.IsQuestAccepted(questId))
return (ImGuiColors.DalamudYellow, FontAwesomeIcon.Running, "Active");