Fix missing class switches for gathering from context me

Should have been in cc8f326d7e, but kinda
forgot. Oops.
This commit is contained in:
Liza 2024-11-11 22:38:20 +01:00
parent ea42b5b8df
commit 7382131246
Signed by: liza
GPG Key ID: 7199F8D727D55F67
20 changed files with 112 additions and 10 deletions

View File

@ -97,6 +97,9 @@ internal static class QuestStepExtensions
.AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),
Assignment(nameof(QuestStep.Status), step.Status, emptyStep.Status) Assignment(nameof(QuestStep.Status), step.Status, emptyStep.Status)
.AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),
Assignment(nameof(QuestStep.TargetClass), step.TargetClass,
emptyStep.TargetClass)
.AsSyntaxNodeOrToken(),
Assignment(nameof(QuestStep.EnemySpawnType), step.EnemySpawnType, Assignment(nameof(QuestStep.EnemySpawnType), step.EnemySpawnType,
emptyStep.EnemySpawnType) emptyStep.EnemySpawnType)
.AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),

View File

@ -5,6 +5,11 @@
{ {
"Sequence": 0, "Sequence": 0,
"Steps": [ "Steps": [
{
"TerritoryId": 478,
"InteractionType": "SwitchClass",
"TargetClass": "Blue Mage"
},
{ {
"TerritoryId": 478, "TerritoryId": 478,
"InteractionType": "Gather", "InteractionType": "Gather",

View File

@ -5,6 +5,11 @@
{ {
"Sequence": 0, "Sequence": 0,
"Steps": [ "Steps": [
{
"TerritoryId": 478,
"InteractionType": "SwitchClass",
"TargetClass": "Blue Mage"
},
{ {
"TerritoryId": 478, "TerritoryId": 478,
"InteractionType": "Gather", "InteractionType": "Gather",

View File

@ -5,6 +5,11 @@
{ {
"Sequence": 0, "Sequence": 0,
"Steps": [ "Steps": [
{
"TerritoryId": 613,
"InteractionType": "SwitchClass",
"TargetClass": "Blue Mage"
},
{ {
"TerritoryId": 613, "TerritoryId": 613,
"InteractionType": "Gather", "InteractionType": "Gather",

View File

@ -5,6 +5,11 @@
{ {
"Sequence": 0, "Sequence": 0,
"Steps": [ "Steps": [
{
"TerritoryId": 635,
"InteractionType": "SwitchClass",
"TargetClass": "Blue Mage"
},
{ {
"TerritoryId": 635, "TerritoryId": 635,
"InteractionType": "Gather", "InteractionType": "Gather",

View File

@ -5,6 +5,11 @@
{ {
"Sequence": 0, "Sequence": 0,
"Steps": [ "Steps": [
{
"TerritoryId": 886,
"InteractionType": "SwitchClass",
"TargetClass": "Blue Mage"
},
{ {
"TerritoryId": 886, "TerritoryId": 886,
"InteractionType": "Gather", "InteractionType": "Gather",

View File

@ -5,6 +5,11 @@
{ {
"Sequence": 0, "Sequence": 0,
"Steps": [ "Steps": [
{
"TerritoryId": 886,
"InteractionType": "SwitchClass",
"TargetClass": "Blue Mage"
},
{ {
"TerritoryId": 886, "TerritoryId": 886,
"InteractionType": "Gather", "InteractionType": "Gather",

View File

@ -5,6 +5,11 @@
{ {
"Sequence": 0, "Sequence": 0,
"Steps": [ "Steps": [
{
"TerritoryId": 820,
"InteractionType": "SwitchClass",
"TargetClass": "Blue Mage"
},
{ {
"TerritoryId": 820, "TerritoryId": 820,
"InteractionType": "Gather", "InteractionType": "Gather",

View File

@ -5,6 +5,11 @@
{ {
"Sequence": 0, "Sequence": 0,
"Steps": [ "Steps": [
{
"TerritoryId": 962,
"InteractionType": "SwitchClass",
"TargetClass": "Blue Mage"
},
{ {
"TerritoryId": 962, "TerritoryId": 962,
"InteractionType": "Gather", "InteractionType": "Gather",

View File

@ -5,6 +5,11 @@
{ {
"Sequence": 0, "Sequence": 0,
"Steps": [ "Steps": [
{
"TerritoryId": 816,
"InteractionType": "SwitchClass",
"TargetClass": "Blue Mage"
},
{ {
"TerritoryId": 816, "TerritoryId": 816,
"InteractionType": "Gather", "InteractionType": "Gather",

View File

@ -5,6 +5,11 @@
{ {
"Sequence": 0, "Sequence": 0,
"Steps": [ "Steps": [
{
"TerritoryId": 956,
"InteractionType": "SwitchClass",
"TargetClass": "Blue Mage"
},
{ {
"TerritoryId": 956, "TerritoryId": 956,
"InteractionType": "Gather", "InteractionType": "Gather",

View File

@ -128,6 +128,7 @@
"Craft", "Craft",
"Gather", "Gather",
"Snipe", "Snipe",
"SwitchClass",
"Instruction", "Instruction",
"AcceptQuest", "AcceptQuest",
"CompleteQuest", "CompleteQuest",
@ -1365,6 +1366,25 @@
"Comment" "Comment"
] ]
} }
},
{
"if": {
"properties": {
"InteractionType": {
"const": "SwitchClass"
}
}
},
"then": {
"properties": {
"TargetClass": {
"$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/ClassJob"
}
},
"required": [
"TargetClass"
]
}
} }
] ]
} }

View File

@ -7,6 +7,7 @@ internal sealed class ExtendedClassJobConverter() : EnumConverter<EExtendedClass
{ {
private static readonly Dictionary<EExtendedClassJob, string> Values = new() private static readonly Dictionary<EExtendedClassJob, string> Values = new()
{ {
{ EExtendedClassJob.None, "None" },
{ EExtendedClassJob.Gladiator, "Gladiator" }, { EExtendedClassJob.Gladiator, "Gladiator" },
{ EExtendedClassJob.Pugilist, "Pugilist" }, { EExtendedClassJob.Pugilist, "Pugilist" },
{ EExtendedClassJob.Marauder, "Marauder" }, { EExtendedClassJob.Marauder, "Marauder" },

View File

@ -31,6 +31,7 @@ public sealed class InteractionTypeConverter() : EnumConverter<EInteractionType>
{ EInteractionType.Craft, "Craft" }, { EInteractionType.Craft, "Craft" },
{ EInteractionType.Gather, "Gather" }, { EInteractionType.Gather, "Gather" },
{ EInteractionType.Snipe, "Snipe" }, { EInteractionType.Snipe, "Snipe" },
{ EInteractionType.SwitchClass, "SwitchClass" },
{ EInteractionType.Instruction, "Instruction" }, { EInteractionType.Instruction, "Instruction" },
{ EInteractionType.AcceptQuest, "AcceptQuest" }, { EInteractionType.AcceptQuest, "AcceptQuest" },
{ EInteractionType.CompleteQuest, "CompleteQuest" }, { EInteractionType.CompleteQuest, "CompleteQuest" },

View File

@ -6,6 +6,7 @@ namespace Questionable.Model.Questing;
[JsonConverter(typeof(ExtendedClassJobConverter))] [JsonConverter(typeof(ExtendedClassJobConverter))]
public enum EExtendedClassJob public enum EExtendedClassJob
{ {
None,
Gladiator, Gladiator,
Pugilist, Pugilist,
Marauder, Marauder,
@ -53,3 +54,4 @@ public enum EExtendedClassJob
DoH, DoH,
DoL, DoL,
} }

View File

@ -30,6 +30,7 @@ public enum EInteractionType
Craft, Craft,
Gather, Gather,
Snipe, Snipe,
SwitchClass,
/// <summary> /// <summary>
/// Needs to be manually continued. /// Needs to be manually continued.

View File

@ -64,6 +64,7 @@ public sealed class QuestStep
public ChatMessage? ChatMessage { get; set; } public ChatMessage? ChatMessage { get; set; }
public EAction? Action { get; set; } public EAction? Action { get; set; }
public EStatus? Status { get; set; } public EStatus? Status { get; set; }
public EExtendedClassJob TargetClass { get; set; } = EExtendedClassJob.None;
public EEnemySpawnType? EnemySpawnType { get; set; } public EEnemySpawnType? EnemySpawnType { get; set; }
public List<uint> KillEnemyDataIds { get; set; } = []; public List<uint> KillEnemyDataIds { get; set; } = [];

View File

@ -71,14 +71,16 @@ internal sealed class ContextMenuController : IDisposable
if (_gatheringData.TryGetCustomDeliveryNpc(itemId, out uint npcId)) if (_gatheringData.TryGetCustomDeliveryNpc(itemId, out uint npcId))
{ {
AddContextMenuEntry(args, itemId, npcId, EClassJob.Miner, "Mine"); AddContextMenuEntry(args, itemId, npcId, EExtendedClassJob.Miner, "Mine");
AddContextMenuEntry(args, itemId, npcId, EClassJob.Botanist, "Harvest"); AddContextMenuEntry(args, itemId, npcId, EExtendedClassJob.Botanist, "Harvest");
} }
} }
private void AddContextMenuEntry(IMenuOpenedArgs args, uint itemId, uint npcId, EClassJob classJob, string verb) private void AddContextMenuEntry(IMenuOpenedArgs args, uint itemId, uint npcId, EExtendedClassJob extendedClassJob,
string verb)
{ {
EClassJob currentClassJob = (EClassJob)_clientState.LocalPlayer!.ClassJob.Id; EClassJob currentClassJob = (EClassJob)_clientState.LocalPlayer!.ClassJob.Id;
EClassJob classJob = ClassJobUtils.AsIndividualJobs(extendedClassJob).Single();
if (classJob != currentClassJob && currentClassJob is EClassJob.Miner or EClassJob.Botanist) if (classJob != currentClassJob && currentClassJob is EClassJob.Miner or EClassJob.Botanist)
return; return;
@ -123,19 +125,25 @@ internal sealed class ContextMenuController : IDisposable
Prefix = SeIconChar.Hyadelyn, Prefix = SeIconChar.Hyadelyn,
PrefixColor = 52, PrefixColor = 52,
Name = name, Name = name,
OnClicked = _ => StartGathering(npcId, itemId, quantityToGather, collectability), OnClicked = _ => StartGathering(npcId, itemId, quantityToGather, collectability, extendedClassJob),
IsEnabled = string.IsNullOrEmpty(lockedReasonn), IsEnabled = string.IsNullOrEmpty(lockedReasonn),
}); });
} }
private void StartGathering(uint npcId, uint itemId, int quantity, ushort collectability) private void StartGathering(uint npcId, uint itemId, int quantity, ushort collectability,
EExtendedClassJob extendedClassJob)
{ {
var info = (SatisfactionSupplyInfo)_questData.GetAllByIssuerDataId(npcId) var info = (SatisfactionSupplyInfo)_questData.GetAllByIssuerDataId(npcId)
.Single(x => x is SatisfactionSupplyInfo); .Single(x => x is SatisfactionSupplyInfo);
if (_questRegistry.TryGetQuest(info.QuestId, out Quest? quest)) if (_questRegistry.TryGetQuest(info.QuestId, out Quest? quest))
{ {
var step = quest.FindSequence(0)!.Steps.Single(x => x.InteractionType == EInteractionType.Gather); var sequence = quest.FindSequence(0)!;
step.ItemsToGather =
var switchClassStep = sequence.Steps.Single(x => x.InteractionType == EInteractionType.SwitchClass);
switchClassStep.TargetClass = extendedClassJob;
var gatherStep = sequence.Steps.Single(x => x.InteractionType == EInteractionType.Gather);
gatherStep.ItemsToGather =
[ [
new GatheredItem new GatheredItem
{ {

View File

@ -1,13 +1,27 @@
using Dalamud.Plugin.Services; using System.Linq;
using FFXIVClientStructs.FFXIV.Client.Game; using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.UI.Misc; using FFXIVClientStructs.FFXIV.Client.UI.Misc;
using LLib.GameData; using LLib.GameData;
using Questionable.Controller.Steps.Common; using Questionable.Controller.Steps.Common;
using Questionable.Data;
using Questionable.Model;
using Questionable.Model.Questing;
namespace Questionable.Controller.Steps.Shared; namespace Questionable.Controller.Steps.Shared;
internal static class SwitchClassJob internal static class SwitchClassJob
{ {
internal sealed class Factory : SimpleTaskFactory
{
public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step)
{
if (step.InteractionType != EInteractionType.SwitchClass)
return null;
EClassJob classJob = ClassJobUtils.AsIndividualJobs(step.TargetClass).Single();
return new Task(classJob);
}
}
internal sealed record Task(EClassJob ClassJob) : ITask internal sealed record Task(EClassJob ClassJob) : ITask
{ {
public override string ToString() => $"SwitchJob({ClassJob})"; public override string ToString() => $"SwitchJob({ClassJob})";

View File

@ -137,7 +137,8 @@ public sealed class QuestionablePlugin : IDalamudPlugin
.AddTaskExecutor<MoveToLandingLocation.Task, MoveToLandingLocation.MoveToLandingLocationExecutor>(); .AddTaskExecutor<MoveToLandingLocation.Task, MoveToLandingLocation.MoveToLandingLocationExecutor>();
serviceCollection.AddTaskExecutor<DoGather.Task, DoGather.GatherExecutor>(); serviceCollection.AddTaskExecutor<DoGather.Task, DoGather.GatherExecutor>();
serviceCollection.AddTaskExecutor<DoGatherCollectable.Task, DoGatherCollectable.GatherCollectableExecutor>(); serviceCollection.AddTaskExecutor<DoGatherCollectable.Task, DoGatherCollectable.GatherCollectableExecutor>();
serviceCollection.AddTaskExecutor<SwitchClassJob.Task, SwitchClassJob.SwitchClassJobExecutor>(); serviceCollection.AddTaskFactoryAndExecutor<SwitchClassJob.Task, SwitchClassJob.Factory,
SwitchClassJob.SwitchClassJobExecutor>();
serviceCollection.AddTaskExecutor<Mount.MountTask, Mount.MountExecutor>(); serviceCollection.AddTaskExecutor<Mount.MountTask, Mount.MountExecutor>();
serviceCollection.AddTaskExecutor<Mount.UnmountTask, Mount.UnmountExecutor>(); serviceCollection.AddTaskExecutor<Mount.UnmountTask, Mount.UnmountExecutor>();