diff --git a/QuestPaths/2.x - A Realm Reborn/Class Quests/NIN/102_My First Dagger.json b/QuestPaths/2.x - A Realm Reborn/Class Quests/NIN/102_My First Dagger.json index bece61c85..e5ffdf92c 100644 --- a/QuestPaths/2.x - A Realm Reborn/Class Quests/NIN/102_My First Dagger.json +++ b/QuestPaths/2.x - A Realm Reborn/Class Quests/NIN/102_My First Dagger.json @@ -29,13 +29,7 @@ }, "TerritoryId": 129, "InteractionType": "Interact", - "DialogueChoices": [ - { - "Type": "YesNo", - "Prompt": "TEXT_CLSROG011_00102_Q9_000_901", - "Yes": true - } - ] + "TargetTerritoryId": 129 }, { "DataId": 1009943, diff --git a/QuestPaths/2.x - A Realm Reborn/Class Quests/NIN/104_Stabbers in Yer Fambles.json b/QuestPaths/2.x - A Realm Reborn/Class Quests/NIN/104_Stabbers in Yer Fambles.json index a87348bb6..e8d5203d6 100644 --- a/QuestPaths/2.x - A Realm Reborn/Class Quests/NIN/104_Stabbers in Yer Fambles.json +++ b/QuestPaths/2.x - A Realm Reborn/Class Quests/NIN/104_Stabbers in Yer Fambles.json @@ -5,6 +5,26 @@ { "Sequence": 0, "Steps": [ + { + "TerritoryId": 129, + "InteractionType": "EquipItem", + "ItemId": 7952, + "AetheryteShortcut": "Limsa Lominsa", + "SkipConditions": { + "AetheryteShortcutIf": { + "InSameTerritory": true + }, + "StepIf": { + "Item": { + "NotInInventory": true + } + } + } + }, + { + "TerritoryId": 129, + "InteractionType": "EquipRecommended" + }, { "DataId": 1009944, "Position": { @@ -14,16 +34,12 @@ }, "TerritoryId": 129, "InteractionType": "Interact", - "AetheryteShortcut": "Limsa Lominsa", "TargetTerritoryId": 129, "AethernetShortcut": [ "[Limsa Lominsa] Aetheryte Plaza", "[Limsa Lominsa] Fishermens' Guild" ], "SkipConditions": { - "AetheryteShortcutIf": { - "InSameTerritory": true - }, "StepIf": { "ExtraCondition": "RoguesGuild" } @@ -45,6 +61,25 @@ { "Sequence": 1, "Steps": [ + { + "DataId": 2004936, + "Position": { + "X": -151.90363, + "Y": -128.16058, + "Z": 256.8551 + }, + "TerritoryId": 129, + "InteractionType": "Interact", + "TargetTerritoryId": 129, + "SkipConditions": { + "StepIf": { + "InTerritory": [ + 134 + ], + "ExtraCondition": "NotRoguesGuild" + } + } + }, { "Position": { "X": 31.662792, diff --git a/QuestPaths/2.x - A Realm Reborn/Class Quests/NIN/110_A Dainty Dilemma.json b/QuestPaths/2.x - A Realm Reborn/Class Quests/NIN/110_A Dainty Dilemma.json index 062d18b9d..deb50f396 100644 --- a/QuestPaths/2.x - A Realm Reborn/Class Quests/NIN/110_A Dainty Dilemma.json +++ b/QuestPaths/2.x - A Realm Reborn/Class Quests/NIN/110_A Dainty Dilemma.json @@ -152,15 +152,9 @@ "TerritoryId": 129, "InteractionType": "Interact", "TargetTerritoryId": 129, - "AethernetShortcut": [ - "[Limsa Lominsa] Fishermens' Guild", - "[Limsa Lominsa] The Aftcastle" - ], "SkipConditions": { "StepIf": { - "InTerritory": [ - 128 - ] + "ExtraCondition": "NotRoguesGuild" } } }, @@ -173,6 +167,10 @@ }, "TerritoryId": 128, "InteractionType": "Interact", + "AethernetShortcut": [ + "[Limsa Lominsa] Fishermens' Guild", + "[Limsa Lominsa] The Aftcastle" + ], "DialogueChoices": [ { "Type": "List", diff --git a/QuestPaths/2.x - A Realm Reborn/Class Quests/NIN/126_Stray into the Shadows.json b/QuestPaths/2.x - A Realm Reborn/Class Quests/NIN/126_Stray into the Shadows.json index bf69b4562..a1b089dc2 100644 --- a/QuestPaths/2.x - A Realm Reborn/Class Quests/NIN/126_Stray into the Shadows.json +++ b/QuestPaths/2.x - A Realm Reborn/Class Quests/NIN/126_Stray into the Shadows.json @@ -291,7 +291,17 @@ "Z": 239.30713 }, "TerritoryId": 129, - "InteractionType": "SinglePlayerDuty" + "InteractionType": "SinglePlayerDuty", + "SinglePlayerDutyOptions": { + "Enabled": false, + "TestedBossModVersion": 292, + "Notes": [ + "(phase 1) AI doesn't move or pick up the stolen firearms", + "(phase 1 + 2) AI automatically removes Hidden status", + "(phase 2) AI only moves while targeted enemies are in range + gets stuck on corners while trying to get to irrelevant enemies", + "(phase 2) AI doesn't even attempt to navigate to the end of the quest" + ] + } } ] }, diff --git a/QuestPaths/5.x - Shadowbringers/MSQ/I-5.3/3775_Faded Memories.json b/QuestPaths/5.x - Shadowbringers/MSQ/I-5.3/3775_Faded Memories.json index 9bd052233..43ab7e588 100644 --- a/QuestPaths/5.x - Shadowbringers/MSQ/I-5.3/3775_Faded Memories.json +++ b/QuestPaths/5.x - Shadowbringers/MSQ/I-5.3/3775_Faded Memories.json @@ -78,6 +78,14 @@ }, "TerritoryId": 918, "InteractionType": "SinglePlayerDuty", + "SinglePlayerDutyOptions": { + "Enabled": false, + "TestedBossModVersion": 292, + "Notes": [ + "(phase 2) AI doesn't target Ardbert to start combat", + "(phase 2) VBM module: Elidibus' line cleave only covers half the length of the actual line (survivable)" + ] + }, "Comment": "Fight NPCs, then Elidibus", "DialogueChoices": [ { diff --git a/QuestPaths/5.x - Shadowbringers/MSQ/J-5.4/4015_The Great Ship Vylbrand.json b/QuestPaths/5.x - Shadowbringers/MSQ/J-5.4/4015_The Great Ship Vylbrand.json index a906fe10a..7b0507022 100644 --- a/QuestPaths/5.x - Shadowbringers/MSQ/J-5.4/4015_The Great Ship Vylbrand.json +++ b/QuestPaths/5.x - Shadowbringers/MSQ/J-5.4/4015_The Great Ship Vylbrand.json @@ -84,7 +84,10 @@ }, "TerritoryId": 180, "InteractionType": "SinglePlayerDuty", - "Comment": "Great Ship Vylbrand" + "SinglePlayerDutyOptions": { + "Enabled": true, + "TestedBossModVersion": 292 + } } ] }, diff --git a/QuestPaths/5.x - Shadowbringers/MSQ/L-5.55/4066_Death Unto Dawn.json b/QuestPaths/5.x - Shadowbringers/MSQ/L-5.55/4066_Death Unto Dawn.json index 2e7967997..ea79f064a 100644 --- a/QuestPaths/5.x - Shadowbringers/MSQ/L-5.55/4066_Death Unto Dawn.json +++ b/QuestPaths/5.x - Shadowbringers/MSQ/L-5.55/4066_Death Unto Dawn.json @@ -46,6 +46,15 @@ "StopDistance": 7, "TerritoryId": 132, "InteractionType": "SinglePlayerDuty", + "SinglePlayerDutyOptions": { + "Enabled": false, + "TestedBossModVersion": 293, + "Notes": [ + "(Lunar Odin) AI doesn't pull Odin to start combat", + "(Lunar Ravana) AI doesn't pull Ravana to start combat", + "(Lunar Ravana) AI doesn't move out of directional parry directions" + ] + }, "Comment": "Death Unto Dawn" } ] diff --git a/Questionable/Controller/CombatModules/BossModModule.cs b/Questionable/Controller/CombatModules/BossModModule.cs index a69237f3e..da951b1e4 100644 --- a/Questionable/Controller/CombatModules/BossModModule.cs +++ b/Questionable/Controller/CombatModules/BossModModule.cs @@ -1,14 +1,7 @@ using Dalamud.Game.ClientState.Objects.Types; -using Dalamud.Plugin; -using Dalamud.Plugin.Ipc; using Dalamud.Plugin.Ipc.Exceptions; -using Dalamud.Plugin.Services; -using Json.Schema; using Microsoft.Extensions.Logging; -using Questionable.Model; using System; -using System.IO; -using System.Numerics; using Questionable.External; namespace Questionable.Controller.CombatModules; @@ -19,8 +12,6 @@ internal sealed class BossModModule : ICombatModule, IDisposable private readonly BossModIpc _bossModIpc; private readonly Configuration _configuration; - private static Stream Preset => typeof(BossModModule).Assembly.GetManifestResourceStream("Questionable.Controller.CombatModules.BossModPreset")!; - public BossModModule( ILogger logger, BossModIpc bossModIpc, @@ -43,12 +34,7 @@ internal sealed class BossModModule : ICombatModule, IDisposable { try { - if (_bossModIpc.GetPreset("Questionable") == null) - { - using var reader = new StreamReader(Preset); - _logger.LogInformation("Loading Questionable BossMod Preset: {LoadedState}", _bossModIpc.CreatePreset(reader.ReadToEnd(), true)); - } - _bossModIpc.SetPreset("Questionable"); + _bossModIpc.SetPreset(BossModIpc.EPreset.Overworld); return true; } catch (IpcError e) diff --git a/Questionable/Controller/CombatModules/BossModPreset_Overworld.json b/Questionable/Controller/CombatModules/BossModPreset_Overworld.json new file mode 100644 index 000000000..a1e032896 --- /dev/null +++ b/Questionable/Controller/CombatModules/BossModPreset_Overworld.json @@ -0,0 +1,293 @@ +{ + "Name": "Questionable", + "Modules": { + "BossMod.Autorotation.xan.DNC": [ + { + "Track": "Buffs", + "Option": "Auto" + }, + { + "Track": "AOE", + "Option": "AOE" + }, + { + "Track": "Targeting", + "Option": "Manual" + } + ], + "BossMod.Autorotation.xan.MCH": [ + { + "Track": "Buffs", + "Option": "Auto" + }, + { + "Track": "AOE", + "Option": "AOE" + }, + { + "Track": "Targeting", + "Option": "Manual" + } + ], + "BossMod.Autorotation.xan.MNK": [ + { + "Track": "AOE", + "Option": "AOE" + }, + { + "Track": "Targeting", + "Option": "Manual" + } + ], + "BossMod.Autorotation.xan.PCT": [ + { + "Track": "Buffs", + "Option": "Auto" + }, + { + "Track": "AOE", + "Option": "AOE" + }, + { + "Track": "Targeting", + "Option": "Manual" + }, + { + "Track": "Motifs", + "Option": "Downtime" + } + ], + "BossMod.Autorotation.xan.PLD": [ + { + "Track": "Buffs", + "Option": "Auto" + }, + { + "Track": "AOE", + "Option": "AOE" + }, + { + "Track": "Targeting", + "Option": "Manual" + } + ], + "BossMod.Autorotation.xan.SAM": [ + { + "Track": "Buffs", + "Option": "Auto" + }, + { + "Track": "AOE", + "Option": "AOE" + }, + { + "Track": "Targeting", + "Option": "Manual" + } + ], + "BossMod.Autorotation.xan.SGE": [ + { + "Track": "AOE", + "Option": "AOE" + }, + { + "Track": "Targeting", + "Option": "Manual" + } + ], + "BossMod.Autorotation.xan.VPR": [ + { + "Track": "Buffs", + "Option": "Auto" + }, + { + "Track": "AOE", + "Option": "AOE" + }, + { + "Track": "Targeting", + "Option": "Manual" + } + ], + "BossMod.Autorotation.xan.NIN": [ + { + "Track": "Buffs", + "Option": "Auto" + }, + { + "Track": "AOE", + "Option": "AOE" + }, + { + "Track": "Targeting", + "Option": "Manual" + } + ], + "BossMod.Autorotation.xan.GNB": [ + { + "Track": "Buffs", + "Option": "Auto" + }, + { + "Track": "AOE", + "Option": "AOE" + }, + { + "Track": "Targeting", + "Option": "Manual" + } + ], + "BossMod.Autorotation.xan.SMN": [ + { + "Track": "Buffs", + "Option": "Auto" + }, + { + "Track": "AOE", + "Option": "AOE" + }, + { + "Track": "Targeting", + "Option": "Manual" + } + ], + "BossMod.Autorotation.xan.DRK": [ + { + "Track": "Buffs", + "Option": "Auto" + }, + { + "Track": "AOE", + "Option": "AOE" + }, + { + "Track": "Targeting", + "Option": "Manual" + } + ], + "BossMod.Autorotation.xan.RPR": [ + { + "Track": "Buffs", + "Option": "Auto" + }, + { + "Track": "AOE", + "Option": "AOE" + }, + { + "Track": "Targeting", + "Option": "Manual" + } + ], + "BossMod.Autorotation.xan.WHM": [ + { + "Track": "Buffs", + "Option": "Auto" + }, + { + "Track": "AOE", + "Option": "AOE" + }, + { + "Track": "Targeting", + "Option": "Manual" + } + ], + "BossMod.Autorotation.xan.AST": [ + { + "Track": "Buffs", + "Option": "Auto" + }, + { + "Track": "AOE", + "Option": "AOE" + }, + { + "Track": "Targeting", + "Option": "Manual" + } + ], + "BossMod.Autorotation.xan.BRD": [ + { + "Track": "Buffs", + "Option": "Auto" + }, + { + "Track": "AOE", + "Option": "AOE" + }, + { + "Track": "Targeting", + "Option": "Manual" + } + ], + "BossMod.Autorotation.xan.SCH": [ + { + "Track": "Buffs", + "Option": "Auto" + }, + { + "Track": "AOE", + "Option": "AOE" + }, + { + "Track": "Targeting", + "Option": "Manual" + } + ], + "BossMod.Autorotation.xan.BLM": [ + { + "Track": "Buffs", + "Option": "Auto" + }, + { + "Track": "AOE", + "Option": "AOE" + }, + { + "Track": "Targeting", + "Option": "Manual" + } + ], + "BossMod.Autorotation.xan.RDM": [ + { + "Track": "Buffs", + "Option": "Auto" + }, + { + "Track": "AOE", + "Option": "AOE" + }, + { + "Track": "Targeting", + "Option": "Manual" + } + ], + "BossMod.Autorotation.xan.DRG": [ + { + "Track": "Buffs", + "Option": "Auto" + }, + { + "Track": "AOE", + "Option": "AOE" + }, + { + "Track": "Targeting", + "Option": "Manual" + } + ], + "BossMod.Autorotation.VeynWAR": [ + { + "Track": "AOE", + "Option": "AutoFinishCombo" + } + ], + "BossMod.Autorotation.MiscAI.NormalMovement": [ + { + "Track": "Destination", + "Option": "Pathfind" + } + ] + } +} diff --git a/Questionable/Controller/CombatModules/BossModPreset.json b/Questionable/Controller/CombatModules/BossModPreset_QuestBattle.json similarity index 99% rename from Questionable/Controller/CombatModules/BossModPreset.json rename to Questionable/Controller/CombatModules/BossModPreset_QuestBattle.json index 26e7070af..1e93d984d 100644 --- a/Questionable/Controller/CombatModules/BossModPreset.json +++ b/Questionable/Controller/CombatModules/BossModPreset_QuestBattle.json @@ -1,5 +1,5 @@ { - "Name": "Questionable", + "Name": "Questionable - Quest Battles", "Modules": { "BossMod.Autorotation.MiscAI.AutoFarm": [], "BossMod.Autorotation.MiscAI.AutoPull": [ diff --git a/Questionable/External/BossModIpc.cs b/Questionable/External/BossModIpc.cs index d157622eb..ca732105f 100644 --- a/Questionable/External/BossModIpc.cs +++ b/Questionable/External/BossModIpc.cs @@ -1,3 +1,7 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; using Dalamud.Plugin; using Dalamud.Plugin.Ipc; using Dalamud.Plugin.Ipc.Exceptions; @@ -9,7 +13,13 @@ namespace Questionable.External; internal sealed class BossModIpc { - private const string Name = "BossMod"; + private const string PluginName = "BossMod"; + + private static readonly ReadOnlyDictionary PresetDefinitions = new Dictionary + { + { EPreset.Overworld, new PresetDefinition("Questionable", "Overworld") }, + { EPreset.QuestBattle, new PresetDefinition("Questionable - Quest Battles", "QuestBattle") }, + }.AsReadOnly(); private readonly Configuration _configuration; private readonly ICommandManager _commandManager; @@ -29,10 +39,10 @@ internal sealed class BossModIpc _commandManager = commandManager; _territoryData = territoryData; - _getPreset = pluginInterface.GetIpcSubscriber($"{Name}.Presets.Get"); - _createPreset = pluginInterface.GetIpcSubscriber($"{Name}.Presets.Create"); - _setPreset = pluginInterface.GetIpcSubscriber($"{Name}.Presets.SetActive"); - _clearPreset = pluginInterface.GetIpcSubscriber($"{Name}.Presets.ClearActive"); + _getPreset = pluginInterface.GetIpcSubscriber($"{PluginName}.Presets.Get"); + _createPreset = pluginInterface.GetIpcSubscriber($"{PluginName}.Presets.Create"); + _setPreset = pluginInterface.GetIpcSubscriber($"{PluginName}.Presets.SetActive"); + _clearPreset = pluginInterface.GetIpcSubscriber($"{PluginName}.Presets.ClearActive"); } public bool IsSupported() @@ -47,19 +57,13 @@ internal sealed class BossModIpc } } - public string? GetPreset(string name) + public void SetPreset(EPreset preset) { - return _getPreset.InvokeFunc(name); - } + var definition = PresetDefinitions[preset]; + if (_getPreset.InvokeFunc(definition.Name) == null) + _createPreset.InvokeFunc(definition.Content, true); - public bool CreatePreset(string name, bool overwrite) - { - return _createPreset.InvokeFunc(name, overwrite); - } - - public void SetPreset(string name) - { - _setPreset.InvokeFunc(name); + _setPreset.InvokeFunc(definition.Name); } public void ClearPreset() @@ -68,11 +72,11 @@ internal sealed class BossModIpc } // TODO this should use your actual rotation plugin, not always vbm - public void EnableAi(string presetName = "VBM Default") + public void EnableAi() { _commandManager.ProcessCommand("/vbmai on"); _commandManager.ProcessCommand("/vbm cfg ZoneModuleConfig EnableQuestBattles true"); - SetPreset(presetName); + SetPreset(EPreset.QuestBattle); } public void DisableAi() @@ -94,12 +98,36 @@ internal sealed class BossModIpc if (!_territoryData.TryGetContentFinderConditionForSoloInstance(questId, dutyOptions.Index, out var cfcData)) return false; - if (_configuration.SinglePlayerDuties.BlacklistedSinglePlayerDutyCfcIds.Contains(cfcData.ContentFinderConditionId)) + if (_configuration.SinglePlayerDuties.BlacklistedSinglePlayerDutyCfcIds.Contains(cfcData + .ContentFinderConditionId)) return false; - if (_configuration.SinglePlayerDuties.WhitelistedSinglePlayerDutyCfcIds.Contains(cfcData.ContentFinderConditionId)) + if (_configuration.SinglePlayerDuties.WhitelistedSinglePlayerDutyCfcIds.Contains(cfcData + .ContentFinderConditionId)) return true; return dutyOptions.Enabled; } + + public enum EPreset + { + Overworld, + QuestBattle, + } + + private sealed class PresetDefinition(string name, string fileName) + { + public string Name { get; } = name; + public string Content { get; } = LoadPreset(fileName); + + private static string LoadPreset(string name) + { + Stream stream = + typeof(BossModIpc).Assembly.GetManifestResourceStream( + $"Questionable.Controller.CombatModules.BossModPreset.{name}") ?? + throw new InvalidOperationException($"Preset {name} was not found"); + using var reader = new StreamReader(stream); + return reader.ReadToEnd(); + } + } } diff --git a/Questionable/Questionable.csproj b/Questionable/Questionable.csproj index 544ba74e8..c9095498f 100644 --- a/Questionable/Questionable.csproj +++ b/Questionable/Questionable.csproj @@ -10,24 +10,28 @@ - - + + - + - + - + - - - - Questionable.Controller.CombatModules.BossModPreset - - + + + + + Questionable.Controller.CombatModules.BossModPreset.Overworld + + + Questionable.Controller.CombatModules.BossModPreset.QuestBattle + +