Add quest battle preset

This commit is contained in:
Liza 2025-02-24 17:50:16 +01:00
parent c7f4865201
commit b213e872da
Signed by: liza
GPG Key ID: 2C41B84815CF6445
12 changed files with 435 additions and 67 deletions

View File

@ -29,13 +29,7 @@
},
"TerritoryId": 129,
"InteractionType": "Interact",
"DialogueChoices": [
{
"Type": "YesNo",
"Prompt": "TEXT_CLSROG011_00102_Q9_000_901",
"Yes": true
}
]
"TargetTerritoryId": 129
},
{
"DataId": 1009943,

View File

@ -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,

View File

@ -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",

View File

@ -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"
]
}
}
]
},

View File

@ -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": [
{

View File

@ -84,7 +84,10 @@
},
"TerritoryId": 180,
"InteractionType": "SinglePlayerDuty",
"Comment": "Great Ship Vylbrand"
"SinglePlayerDutyOptions": {
"Enabled": true,
"TestedBossModVersion": 292
}
}
]
},

View File

@ -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"
}
]

View File

@ -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<BossModModule> 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)

View File

@ -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"
}
]
}
}

View File

@ -1,5 +1,5 @@
{
"Name": "Questionable",
"Name": "Questionable - Quest Battles",
"Modules": {
"BossMod.Autorotation.MiscAI.AutoFarm": [],
"BossMod.Autorotation.MiscAI.AutoPull": [

View File

@ -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<EPreset, PresetDefinition> PresetDefinitions = new Dictionary<EPreset, PresetDefinition>
{
{ 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<string, string?>($"{Name}.Presets.Get");
_createPreset = pluginInterface.GetIpcSubscriber<string, bool, bool>($"{Name}.Presets.Create");
_setPreset = pluginInterface.GetIpcSubscriber<string, bool>($"{Name}.Presets.SetActive");
_clearPreset = pluginInterface.GetIpcSubscriber<bool>($"{Name}.Presets.ClearActive");
_getPreset = pluginInterface.GetIpcSubscriber<string, string?>($"{PluginName}.Presets.Get");
_createPreset = pluginInterface.GetIpcSubscriber<string, bool, bool>($"{PluginName}.Presets.Create");
_setPreset = pluginInterface.GetIpcSubscriber<string, bool>($"{PluginName}.Presets.SetActive");
_clearPreset = pluginInterface.GetIpcSubscriber<bool>($"{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();
}
}
}

View File

@ -10,24 +10,28 @@
<ItemGroup>
<PackageReference Include="Dalamud.Extensions.MicrosoftLogging" Version="4.0.1"/>
<PackageReference Include="JetBrains.Annotations" Version="2024.2.0" ExcludeAssets="runtime" />
<PackageReference Include="JsonSchema.Net" Version="7.1.2" />
<PackageReference Include="JetBrains.Annotations" Version="2024.2.0" ExcludeAssets="runtime"/>
<PackageReference Include="JsonSchema.Net" Version="7.1.2"/>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0"/>
<PackageReference Include="System.Text.Json" Version="8.0.5" />
<PackageReference Include="System.Text.Json" Version="8.0.5"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GatheringPaths\GatheringPaths.csproj" />
<ProjectReference Include="..\GatheringPaths\GatheringPaths.csproj"/>
<ProjectReference Include="..\LLib\LLib.csproj"/>
<ProjectReference Include="..\Questionable.Model\Questionable.Model.csproj"/>
<ProjectReference Include="..\QuestPaths\QuestPaths.csproj"/>
<ProjectReference Include="..\vendor\NotificationMasterAPI\NotificationMasterAPI\NotificationMasterAPI.csproj" />
<ProjectReference Include="..\vendor\NotificationMasterAPI\NotificationMasterAPI\NotificationMasterAPI.csproj"/>
</ItemGroup>
<ItemGroup>
<None Remove="Controller\CombatModules\BossModPreset.json" />
<EmbeddedResource Include="Controller\CombatModules\BossModPreset.json">
<LogicalName>Questionable.Controller.CombatModules.BossModPreset</LogicalName>
<None Remove="Controller\CombatModules\BossModPreset_Overworld.json"/>
<None Remove="Controller\CombatModules\BossModPreset.QuestBattle.json"/>
<EmbeddedResource Include="Controller\CombatModules\BossModPreset_Overworld.json">
<LogicalName>Questionable.Controller.CombatModules.BossModPreset.Overworld</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Controller\CombatModules\BossModPreset_QuestBattle.json">
<LogicalName>Questionable.Controller.CombatModules.BossModPreset.QuestBattle</LogicalName>
</EmbeddedResource>
</ItemGroup>
</Project>