Fix missing class switches for gathering from context me
authorLiza Carvelli <liza@carvel.li>
Mon, 11 Nov 2024 21:38:20 +0000 (22:38 +0100)
committerLiza Carvelli <liza@carvel.li>
Mon, 11 Nov 2024 21:39:01 +0000 (22:39 +0100)
Should have been in cc8f326d7ea10afefcb0d5a8e7ae5dae99ba9ea1, but kinda
forgot. Oops.

20 files changed:
QuestPathGenerator/RoslynElements/QuestStepExtensions.cs
QuestPaths/3.x - Heavensward/Custom Deliveries/Zhloe/S1_Zhloe Aliapoh.json
QuestPaths/4.x - Stormblood/Custom Deliveries/Adkiragh/S4_Adkiragh.json
QuestPaths/4.x - Stormblood/Custom Deliveries/Kurenai/S3_Kurenai.json
QuestPaths/4.x - Stormblood/Custom Deliveries/M'naago/S2_M'naago.json
QuestPaths/5.x - Shadowbringers/Custom Deliveries/Charlemend/S7_Charlemend.json
QuestPaths/5.x - Shadowbringers/Custom Deliveries/Ehll Tou/S6_Ehll Tou.json
QuestPaths/5.x - Shadowbringers/Custom Deliveries/Kai-Shirr/S5_Kai-Shirr.json
QuestPaths/6.x - Endwalker/Custom Deliveries/Ameliance/S8_Ameliance.json
QuestPaths/6.x - Endwalker/Custom Deliveries/Anden/S9_Anden.json
QuestPaths/6.x - Endwalker/Custom Deliveries/Margrat/S10_Margrat.json
QuestPaths/quest-v1.json
Questionable.Model/Questing/Converter/ExtendedClassJobConverter.cs
Questionable.Model/Questing/Converter/InteractionTypeConverter.cs
Questionable.Model/Questing/EExtendedClassJob.cs
Questionable.Model/Questing/EInteractionType.cs
Questionable.Model/Questing/QuestStep.cs
Questionable/Controller/ContextMenuController.cs
Questionable/Controller/Steps/Shared/SwitchClassJob.cs
Questionable/QuestionablePlugin.cs

index ecfea639e5a9dacba1d1e1c2f7263727a5fa60e1..12b27ef4eac5c5b82ca11208a6a944d9dafc5594 100644 (file)
@@ -97,6 +97,9 @@ internal static class QuestStepExtensions
                                 .AsSyntaxNodeOrToken(),
                             Assignment(nameof(QuestStep.Status), step.Status, emptyStep.Status)
                                 .AsSyntaxNodeOrToken(),
+                            Assignment(nameof(QuestStep.TargetClass), step.TargetClass,
+                                    emptyStep.TargetClass)
+                                .AsSyntaxNodeOrToken(),
                             Assignment(nameof(QuestStep.EnemySpawnType), step.EnemySpawnType,
                                     emptyStep.EnemySpawnType)
                                 .AsSyntaxNodeOrToken(),
index 1422190e154bc638110712912de5925e3465605e..87ef448e07c74df7be8036ac0b8ffdc83d4baad1 100644 (file)
@@ -5,6 +5,11 @@
     {
       "Sequence": 0,
       "Steps": [
+        {
+          "TerritoryId": 478,
+          "InteractionType": "SwitchClass",
+          "TargetClass": "Blue Mage"
+        },
         {
           "TerritoryId": 478,
           "InteractionType": "Gather",
index 99762b5b2662f1b380ddefd99a9a878323b80d4f..cf54ae7c11bc8d744866c3293f4e82a63095bdec 100644 (file)
@@ -5,6 +5,11 @@
     {
       "Sequence": 0,
       "Steps": [
+        {
+          "TerritoryId": 478,
+          "InteractionType": "SwitchClass",
+          "TargetClass": "Blue Mage"
+        },
         {
           "TerritoryId": 478,
           "InteractionType": "Gather",
index 9b1f82dc3a1307a5b421cf7ed7b672f5059410e3..887dbdd430dcc19c6960baa8f64c6311c2ad5a8b 100644 (file)
@@ -5,6 +5,11 @@
     {
       "Sequence": 0,
       "Steps": [
+        {
+          "TerritoryId": 613,
+          "InteractionType": "SwitchClass",
+          "TargetClass": "Blue Mage"
+        },
         {
           "TerritoryId": 613,
           "InteractionType": "Gather",
index ba9858d8733877b1c97fe122dc0514ef0f4ff031..43cd2ebc05f7da7b186b21c0756f0e2dbb5330f0 100644 (file)
@@ -5,6 +5,11 @@
     {
       "Sequence": 0,
       "Steps": [
+        {
+          "TerritoryId": 635,
+          "InteractionType": "SwitchClass",
+          "TargetClass": "Blue Mage"
+        },
         {
           "TerritoryId": 635,
           "InteractionType": "Gather",
index 18b2d6482971d4c93b42bd360b6fef46990ee617..169f78bd318d96ec9a86aede65fbd22ab1bc5dbc 100644 (file)
@@ -5,6 +5,11 @@
     {
       "Sequence": 0,
       "Steps": [
+        {
+          "TerritoryId": 886,
+          "InteractionType": "SwitchClass",
+          "TargetClass": "Blue Mage"
+        },
         {
           "TerritoryId": 886,
           "InteractionType": "Gather",
index ec41fc8cf6b68ffce1df78a0743d1fdfc14a0a99..adc20fb69c11c93d12b18d72a4d84da00d7dc50b 100644 (file)
@@ -5,6 +5,11 @@
     {
       "Sequence": 0,
       "Steps": [
+        {
+          "TerritoryId": 886,
+          "InteractionType": "SwitchClass",
+          "TargetClass": "Blue Mage"
+        },
         {
           "TerritoryId": 886,
           "InteractionType": "Gather",
index 007020533594758de25b578abb4a1d9965dbdaed..7e4b595ddda889e06462c2ee0440d97d3973c355 100644 (file)
@@ -5,6 +5,11 @@
     {
       "Sequence": 0,
       "Steps": [
+        {
+          "TerritoryId": 820,
+          "InteractionType": "SwitchClass",
+          "TargetClass": "Blue Mage"
+        },
         {
           "TerritoryId": 820,
           "InteractionType": "Gather",
index 9cd56890f18fdb2f972663330e26558cab29edcc..56f16b92060aac51ed1966ab9344eb579e26dec9 100644 (file)
@@ -5,6 +5,11 @@
     {
       "Sequence": 0,
       "Steps": [
+        {
+          "TerritoryId": 962,
+          "InteractionType": "SwitchClass",
+          "TargetClass": "Blue Mage"
+        },
         {
           "TerritoryId": 962,
           "InteractionType": "Gather",
index b36972b05dd31a78e7132b90edbc2bf798f022f8..8f0e18313821afb1bba2ae4a8e4ba23b39ab6cd2 100644 (file)
@@ -5,6 +5,11 @@
     {
       "Sequence": 0,
       "Steps": [
+        {
+          "TerritoryId": 816,
+          "InteractionType": "SwitchClass",
+          "TargetClass": "Blue Mage"
+        },
         {
           "TerritoryId": 816,
           "InteractionType": "Gather",
index e4d27b17c9a8f1108376edf02de3c25372e055fa..6bd9ee4a53f387fbe37e6b23f538ec12d6ccf77a 100644 (file)
@@ -5,6 +5,11 @@
     {
       "Sequence": 0,
       "Steps": [
+        {
+          "TerritoryId": 956,
+          "InteractionType": "SwitchClass",
+          "TargetClass": "Blue Mage"
+        },
         {
           "TerritoryId": 956,
           "InteractionType": "Gather",
index 58c1d16a4c1705c56a0418a1ae58bc9b8730a7e5..72ee631835db39a4cd53983021ae55cd65ff26d4 100644 (file)
             "Craft",
             "Gather",
             "Snipe",
+            "SwitchClass",
             "Instruction",
             "AcceptQuest",
             "CompleteQuest",
               "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"
+            ]
+          }
         }
       ]
     }
index c92ca0bc661baa07b3e14355edaa690454841fea..2eaffe5e99fdf41088252a79506bede1ed11c2e0 100644 (file)
@@ -7,6 +7,7 @@ internal sealed class ExtendedClassJobConverter() : EnumConverter<EExtendedClass
 {
     private static readonly Dictionary<EExtendedClassJob, string> Values = new()
     {
+        { EExtendedClassJob.None, "None" },
         { EExtendedClassJob.Gladiator, "Gladiator" },
         { EExtendedClassJob.Pugilist, "Pugilist" },
         { EExtendedClassJob.Marauder, "Marauder" },
index b8367ebbbba14fb9917d5451dcc85002ae59fbef..9de1ad0ef42293dc54724ae0dcd9f50c33963e69 100644 (file)
@@ -31,6 +31,7 @@ public sealed class InteractionTypeConverter() : EnumConverter<EInteractionType>
         { EInteractionType.Craft, "Craft" },
         { EInteractionType.Gather, "Gather" },
         { EInteractionType.Snipe, "Snipe" },
+        { EInteractionType.SwitchClass, "SwitchClass" },
         { EInteractionType.Instruction, "Instruction" },
         { EInteractionType.AcceptQuest, "AcceptQuest" },
         { EInteractionType.CompleteQuest, "CompleteQuest" },
index 79c771d11b5506b20761189c6313f99fb5f5435c..e0f0d3fe952dd2a875584ea8fef241234151ae9d 100644 (file)
@@ -6,6 +6,7 @@ namespace Questionable.Model.Questing;
 [JsonConverter(typeof(ExtendedClassJobConverter))]
 public enum EExtendedClassJob
 {
+    None,
     Gladiator,
     Pugilist,
     Marauder,
@@ -53,3 +54,4 @@ public enum EExtendedClassJob
     DoH,
     DoL,
 }
+
index 137078ebab4105c7317ecb1cc56380cfa7a98a0e..2b9a75fc39595a9a24f041c23c699050d85d1a40 100644 (file)
@@ -30,6 +30,7 @@ public enum EInteractionType
     Craft,
     Gather,
     Snipe,
+    SwitchClass,
 
     /// <summary>
     /// Needs to be manually continued.
index df2b7b12800aa25ef79caa5de780926ea3c734cc..0b4a05a21dbfd4ee9fc8b39b8f643a11b479d590 100644 (file)
@@ -64,6 +64,7 @@ public sealed class QuestStep
     public ChatMessage? ChatMessage { get; set; }
     public EAction? Action { get; set; }
     public EStatus? Status { get; set; }
+    public EExtendedClassJob TargetClass { get; set; } = EExtendedClassJob.None;
 
     public EEnemySpawnType? EnemySpawnType { get; set; }
     public List<uint> KillEnemyDataIds { get; set; } = [];
index f35e834321dd259b084764bb822b897eae8d5fed..c3d6c4c5d3a74709eed68e971315f29ae17b4200 100644 (file)
@@ -71,14 +71,16 @@ internal sealed class ContextMenuController : IDisposable
 
         if (_gatheringData.TryGetCustomDeliveryNpc(itemId, out uint npcId))
         {
-            AddContextMenuEntry(args, itemId, npcId, EClassJob.Miner, "Mine");
-            AddContextMenuEntry(args, itemId, npcId, EClassJob.Botanist, "Harvest");
+            AddContextMenuEntry(args, itemId, npcId, EExtendedClassJob.Miner, "Mine");
+            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 classJob = ClassJobUtils.AsIndividualJobs(extendedClassJob).Single();
         if (classJob != currentClassJob && currentClassJob is EClassJob.Miner or EClassJob.Botanist)
             return;
 
@@ -123,19 +125,25 @@ internal sealed class ContextMenuController : IDisposable
             Prefix = SeIconChar.Hyadelyn,
             PrefixColor = 52,
             Name = name,
-            OnClicked = _ => StartGathering(npcId, itemId, quantityToGather, collectability),
+            OnClicked = _ => StartGathering(npcId, itemId, quantityToGather, collectability, extendedClassJob),
             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)
             .Single(x => x is SatisfactionSupplyInfo);
         if (_questRegistry.TryGetQuest(info.QuestId, out Quest? quest))
         {
-            var step = quest.FindSequence(0)!.Steps.Single(x => x.InteractionType == EInteractionType.Gather);
-            step.ItemsToGather =
+            var sequence = quest.FindSequence(0)!;
+
+            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
                 {
index 37ddf1eebc887c2a344fcd3c8ece4a0f3d371500..48b153c3a4c2d9109cb366d570b83b5da193044b 100644 (file)
@@ -1,13 +1,27 @@
-using Dalamud.Plugin.Services;
-using FFXIVClientStructs.FFXIV.Client.Game;
+using System.Linq;
+using Dalamud.Plugin.Services;
 using FFXIVClientStructs.FFXIV.Client.UI.Misc;
 using LLib.GameData;
 using Questionable.Controller.Steps.Common;
+using Questionable.Data;
+using Questionable.Model;
+using Questionable.Model.Questing;
 
 namespace Questionable.Controller.Steps.Shared;
 
 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
     {
         public override string ToString() => $"SwitchJob({ClassJob})";
index 9289b1206b5cd9bbf7fd7cf959ccd899667bcc43..ea0eefca40f5b98b742bbb49e63190d57c331e3e 100644 (file)
@@ -137,7 +137,8 @@ public sealed class QuestionablePlugin : IDalamudPlugin
             .AddTaskExecutor<MoveToLandingLocation.Task, MoveToLandingLocation.MoveToLandingLocationExecutor>();
         serviceCollection.AddTaskExecutor<DoGather.Task, DoGather.GatherExecutor>();
         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.UnmountTask, Mount.UnmountExecutor>();