forked from liza/Questionable
Draft for auto-completing quest battles (HW MSQ)
This commit is contained in:
parent
b35ee13704
commit
92873554cc
@ -123,6 +123,9 @@ internal static class QuestStepExtensions
|
||||
Assignment(nameof(QuestStep.AutoDutyEnabled),
|
||||
step.AutoDutyEnabled, emptyStep.AutoDutyEnabled)
|
||||
.AsSyntaxNodeOrToken(),
|
||||
Assignment(nameof(QuestStep.BossModEnabled),
|
||||
step.BossModEnabled, emptyStep.BossModEnabled)
|
||||
.AsSyntaxNodeOrToken(),
|
||||
Assignment(nameof(QuestStep.SkipConditions), step.SkipConditions,
|
||||
emptyStep.SkipConditions)
|
||||
.AsSyntaxNodeOrToken(),
|
||||
|
@ -95,7 +95,9 @@
|
||||
},
|
||||
"TerritoryId": 138,
|
||||
"InteractionType": "SinglePlayerDuty",
|
||||
"Fly": true
|
||||
"Fly": true,
|
||||
"ContentFinderConditionId": 393,
|
||||
"BossModEnabled": true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -58,7 +58,9 @@
|
||||
"Z": 349.96558
|
||||
},
|
||||
"TerritoryId": 401,
|
||||
"InteractionType": "SinglePlayerDuty"
|
||||
"InteractionType": "SinglePlayerDuty",
|
||||
"ContentFinderConditionId": 395,
|
||||
"BossModEnabled": true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -78,7 +78,9 @@
|
||||
"AethernetShortcut": [
|
||||
"[Ishgard] The Forgotten Knight",
|
||||
"[Ishgard] The Tribunal"
|
||||
]
|
||||
],
|
||||
"ContentFinderConditionId": 396,
|
||||
"BossModEnabled": true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -28,7 +28,9 @@
|
||||
"Z": 388.63196
|
||||
},
|
||||
"TerritoryId": 145,
|
||||
"InteractionType": "SinglePlayerDuty"
|
||||
"InteractionType": "SinglePlayerDuty",
|
||||
"ContentFinderConditionId": 400,
|
||||
"BossModEnabled": true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -21,6 +21,16 @@
|
||||
{
|
||||
"Sequence": 1,
|
||||
"Steps": [
|
||||
{
|
||||
"Position": {
|
||||
"X": 474.62885,
|
||||
"Y": 200.2377,
|
||||
"Z": 657.9519
|
||||
},
|
||||
"TerritoryId": 397,
|
||||
"InteractionType": "WalkTo",
|
||||
"AetheryteShortcut": "Coerthas Western Highlands - Falcon's Nest"
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"X": 486.38373,
|
||||
@ -28,8 +38,7 @@
|
||||
"Z": 239.54294
|
||||
},
|
||||
"TerritoryId": 397,
|
||||
"InteractionType": "WalkTo",
|
||||
"AetheryteShortcut": "Coerthas Western Highlands - Falcon's Nest"
|
||||
"InteractionType": "WalkTo"
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
@ -69,7 +78,9 @@
|
||||
},
|
||||
"TerritoryId": 397,
|
||||
"InteractionType": "SinglePlayerDuty",
|
||||
"DisableNavmesh": true
|
||||
"DisableNavmesh": true,
|
||||
"ContentFinderConditionId": 397,
|
||||
"BossModEnabled": true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -59,7 +59,14 @@
|
||||
"KillEnemyDataIds": [
|
||||
4015
|
||||
],
|
||||
"$": "0 0 0 0 0 0 -> "
|
||||
"CompletionQuestVariablesFlags": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
128
|
||||
]
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
@ -72,6 +79,14 @@
|
||||
"EnemySpawnType": "AutoOnEnterArea",
|
||||
"KillEnemyDataIds": [
|
||||
4015
|
||||
],
|
||||
"CompletionQuestVariablesFlags": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
64
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -89,6 +89,16 @@
|
||||
"InteractionType": "WalkTo",
|
||||
"Mount": true
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"X": -335.0186,
|
||||
"Y": 13.983504,
|
||||
"Z": -100.87753
|
||||
},
|
||||
"TerritoryId": 140,
|
||||
"InteractionType": "WalkTo",
|
||||
"Fly": true
|
||||
},
|
||||
{
|
||||
"DataId": 1004019,
|
||||
"Position": {
|
||||
@ -98,7 +108,6 @@
|
||||
},
|
||||
"TerritoryId": 140,
|
||||
"InteractionType": "Interact",
|
||||
"Fly": true,
|
||||
"TargetTerritoryId": 140
|
||||
},
|
||||
{
|
||||
|
@ -74,7 +74,9 @@
|
||||
"Z": 37.247192
|
||||
},
|
||||
"TerritoryId": 418,
|
||||
"InteractionType": "SinglePlayerDuty"
|
||||
"InteractionType": "SinglePlayerDuty",
|
||||
"ContentFinderConditionId": 398,
|
||||
"BossModEnabled": true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -56,7 +56,9 @@
|
||||
"TerritoryId": 401,
|
||||
"InteractionType": "SinglePlayerDuty",
|
||||
"Emote": "lookout",
|
||||
"StopDistance": 0.25
|
||||
"StopDistance": 0.25,
|
||||
"ContentFinderConditionId": 401,
|
||||
"BossModEnabled": true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -47,7 +47,9 @@
|
||||
"AethernetShortcut": [
|
||||
"[Idyllshire] Aetheryte Plaza",
|
||||
"[Idyllshire] Epilogue Gate (Eastern Hinterlands)"
|
||||
]
|
||||
],
|
||||
"ContentFinderConditionId": 422,
|
||||
"BossModEnabled": true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -68,7 +68,9 @@
|
||||
"Z": 553.97876
|
||||
},
|
||||
"TerritoryId": 402,
|
||||
"InteractionType": "SinglePlayerDuty"
|
||||
"InteractionType": "SinglePlayerDuty",
|
||||
"ContentFinderConditionId": 399,
|
||||
"BossModEnabled": true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1257,6 +1257,27 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"InteractionType": {
|
||||
"const": "SinglePlayerDuty"
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"ContentFinderConditionId": {
|
||||
"type": "integer",
|
||||
"exclusiveMinimum": 0,
|
||||
"exclusiveMaximum": 3000
|
||||
},
|
||||
"BossModEnabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
|
@ -75,6 +75,7 @@ public sealed class QuestStep
|
||||
public JumpDestination? JumpDestination { get; set; }
|
||||
public uint? ContentFinderConditionId { get; set; }
|
||||
public bool AutoDutyEnabled { get; set; }
|
||||
public bool BossModEnabled { get; set; }
|
||||
public SkipConditions? SkipConditions { get; set; }
|
||||
|
||||
public List<List<QuestWorkValue>?> RequiredQuestVariables { get; set; } = new();
|
||||
|
@ -9,33 +9,26 @@ using Questionable.Model;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using Questionable.External;
|
||||
|
||||
namespace Questionable.Controller.CombatModules;
|
||||
|
||||
internal sealed class BossModModule : ICombatModule, IDisposable
|
||||
{
|
||||
private const string Name = "BossMod";
|
||||
private readonly ILogger<BossModModule> _logger;
|
||||
private readonly BossModIpc _bossModIpc;
|
||||
private readonly Configuration _configuration;
|
||||
private readonly ICallGateSubscriber<string, string?> _getPreset;
|
||||
private readonly ICallGateSubscriber<string, bool, bool> _createPreset;
|
||||
private readonly ICallGateSubscriber<string, bool> _setPreset;
|
||||
private readonly ICallGateSubscriber<bool> _clearPreset;
|
||||
|
||||
private static Stream Preset => typeof(BossModModule).Assembly.GetManifestResourceStream("Questionable.Controller.CombatModules.BossModPreset")!;
|
||||
|
||||
public BossModModule(
|
||||
ILogger<BossModModule> logger,
|
||||
IDalamudPluginInterface pluginInterface,
|
||||
BossModIpc bossModIpc,
|
||||
Configuration configuration)
|
||||
{
|
||||
_logger = logger;
|
||||
_bossModIpc = bossModIpc;
|
||||
_configuration = configuration;
|
||||
|
||||
_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");
|
||||
}
|
||||
|
||||
public bool CanHandleFight(CombatController.CombatData combatData)
|
||||
@ -43,26 +36,19 @@ internal sealed class BossModModule : ICombatModule, IDisposable
|
||||
if (_configuration.General.CombatModule != Configuration.ECombatModule.BossMod)
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
return _getPreset.HasFunction;
|
||||
}
|
||||
catch (IpcError)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return _bossModIpc.IsSupported();
|
||||
}
|
||||
|
||||
public bool Start(CombatController.CombatData combatData)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_getPreset.InvokeFunc("Questionable") == null)
|
||||
if (_bossModIpc.GetPreset("Questionable") == null)
|
||||
{
|
||||
using var reader = new StreamReader(Preset);
|
||||
_logger.LogInformation("Loading Questionable BossMod Preset: {LoadedState}", _createPreset.InvokeFunc(reader.ReadToEnd(), true));
|
||||
_logger.LogInformation("Loading Questionable BossMod Preset: {LoadedState}", _bossModIpc.CreatePreset(reader.ReadToEnd(), true));
|
||||
}
|
||||
_setPreset.InvokeFunc("Questionable");
|
||||
_bossModIpc.SetPreset("Questionable");
|
||||
return true;
|
||||
}
|
||||
catch (IpcError e)
|
||||
@ -76,7 +62,7 @@ internal sealed class BossModModule : ICombatModule, IDisposable
|
||||
{
|
||||
try
|
||||
{
|
||||
_clearPreset.InvokeFunc();
|
||||
_bossModIpc.ClearPreset();
|
||||
return true;
|
||||
}
|
||||
catch (IpcError e)
|
||||
|
@ -598,14 +598,14 @@ internal sealed class InteractionUiController : IDisposable
|
||||
if (checkAllSteps)
|
||||
{
|
||||
var sequence = quest.FindSequence(currentQuest.Sequence);
|
||||
if (sequence != null && HandleDefaultYesNo(addonSelectYesno, quest,
|
||||
sequence.Steps.SelectMany(x => x.DialogueChoices).ToList(), actualPrompt))
|
||||
if (sequence != null &&
|
||||
sequence.Steps.Any(step => HandleDefaultYesNo(addonSelectYesno, quest, step, step.DialogueChoices, actualPrompt)))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var step = quest.FindSequence(currentQuest.Sequence)?.FindStep(currentQuest.Step);
|
||||
if (step != null && HandleDefaultYesNo(addonSelectYesno, quest, step.DialogueChoices, actualPrompt))
|
||||
if (step != null && HandleDefaultYesNo(addonSelectYesno, quest, step, step.DialogueChoices, actualPrompt))
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -619,7 +619,7 @@ internal sealed class InteractionUiController : IDisposable
|
||||
Yes = true
|
||||
};
|
||||
|
||||
if (HandleDefaultYesNo(addonSelectYesno, quest, [dialogueChoice], actualPrompt))
|
||||
if (HandleDefaultYesNo(addonSelectYesno, quest, null, [dialogueChoice], actualPrompt))
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -630,7 +630,7 @@ internal sealed class InteractionUiController : IDisposable
|
||||
}
|
||||
|
||||
private unsafe bool HandleDefaultYesNo(AddonSelectYesno* addonSelectYesno, Quest quest,
|
||||
List<DialogueChoice> dialogueChoices, string actualPrompt)
|
||||
QuestStep? step, List<DialogueChoice> dialogueChoices, string actualPrompt)
|
||||
{
|
||||
_logger.LogTrace("DefaultYesNo: Choice count: {Count}", dialogueChoices.Count);
|
||||
foreach (var dialogueChoice in dialogueChoices)
|
||||
@ -659,6 +659,13 @@ internal sealed class InteractionUiController : IDisposable
|
||||
return true;
|
||||
}
|
||||
|
||||
if (step is { InteractionType: EInteractionType.SinglePlayerDuty, BossModEnabled: true })
|
||||
{
|
||||
_logger.LogTrace("DefaultYesNo: probably Single Player Duty");
|
||||
addonSelectYesno->AtkUnitBase.FireCallbackInt(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,8 @@ internal sealed class QuestRegistry
|
||||
foreach (var quest in _quests.Values)
|
||||
{
|
||||
foreach (var dutyStep in quest.AllSteps().Where(x =>
|
||||
x.Step.InteractionType == EInteractionType.Duty && x.Step.ContentFinderConditionId != null))
|
||||
x.Step.InteractionType is EInteractionType.Duty or EInteractionType.SinglePlayerDuty
|
||||
&& x.Step.ContentFinderConditionId != null))
|
||||
{
|
||||
_contentFinderConditionIds[dutyStep.Step.ContentFinderConditionId!.Value] = (quest.Id, dutyStep.Step);
|
||||
}
|
||||
|
@ -26,7 +26,8 @@ internal static class SendNotification
|
||||
new Task(step.InteractionType, step.ContentFinderConditionId.HasValue
|
||||
? territoryData.GetContentFinderCondition(step.ContentFinderConditionId.Value)?.Name
|
||||
: step.Comment),
|
||||
EInteractionType.SinglePlayerDuty => new Task(step.InteractionType, quest.Info.Name),
|
||||
EInteractionType.SinglePlayerDuty when !step.BossModEnabled =>
|
||||
new Task(step.InteractionType, quest.Info.Name),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
124
Questionable/Controller/Steps/Interactions/SinglePlayerDuty.cs
Normal file
124
Questionable/Controller/Steps/Interactions/SinglePlayerDuty.cs
Normal file
@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Dalamud.Plugin.Services;
|
||||
using Questionable.Controller.Steps.Shared;
|
||||
using Questionable.Data;
|
||||
using Questionable.External;
|
||||
using Questionable.Model;
|
||||
using Questionable.Model.Questing;
|
||||
|
||||
namespace Questionable.Controller.Steps.Interactions;
|
||||
|
||||
internal static class SinglePlayerDuty
|
||||
{
|
||||
internal sealed class Factory : ITaskFactory
|
||||
{
|
||||
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
|
||||
{
|
||||
if (step.InteractionType != EInteractionType.SinglePlayerDuty)
|
||||
yield break;
|
||||
|
||||
if (step.BossModEnabled)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(step.ContentFinderConditionId);
|
||||
|
||||
yield return new StartSinglePlayerDuty(step.ContentFinderConditionId.Value);
|
||||
yield return new EnableAi();
|
||||
yield return new WaitSinglePlayerDuty(step.ContentFinderConditionId.Value);
|
||||
yield return new DisableAi();
|
||||
yield return new WaitAtEnd.WaitNextStepOrSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed record StartSinglePlayerDuty(uint ContentFinderConditionId) : ITask
|
||||
{
|
||||
public override string ToString() => $"Wait(BossMod, entered instance {ContentFinderConditionId})";
|
||||
}
|
||||
|
||||
internal sealed class StartSinglePlayerDutyExecutor(
|
||||
TerritoryData territoryData,
|
||||
IClientState clientState) : TaskExecutor<StartSinglePlayerDuty>
|
||||
{
|
||||
protected override bool Start() => true;
|
||||
|
||||
public override ETaskResult Update()
|
||||
{
|
||||
if (!territoryData.TryGetContentFinderCondition(Task.ContentFinderConditionId,
|
||||
out var cfcData))
|
||||
throw new TaskException("Failed to get territory ID for content finder condition");
|
||||
|
||||
return clientState.TerritoryType == cfcData.TerritoryId
|
||||
? ETaskResult.TaskComplete
|
||||
: ETaskResult.StillRunning;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
internal sealed record EnableAi : ITask
|
||||
{
|
||||
public override string ToString() => "BossMod.EnableAi";
|
||||
}
|
||||
|
||||
internal sealed class EnableAiExecutor(
|
||||
BossModIpc bossModIpc) : TaskExecutor<EnableAi>
|
||||
{
|
||||
protected override bool Start()
|
||||
{
|
||||
bossModIpc.EnableAi();
|
||||
return true;
|
||||
}
|
||||
|
||||
public override ETaskResult Update() => ETaskResult.TaskComplete;
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
internal sealed record WaitSinglePlayerDuty(uint ContentFinderConditionId) : ITask
|
||||
{
|
||||
public override string ToString() => $"Wait(BossMod, left instance {ContentFinderConditionId})";
|
||||
}
|
||||
|
||||
internal sealed class WaitSinglePlayerDutyExecutor(
|
||||
TerritoryData territoryData,
|
||||
IClientState clientState,
|
||||
BossModIpc bossModIpc) : TaskExecutor<WaitSinglePlayerDuty>, IStoppableTaskExecutor
|
||||
{
|
||||
protected override bool Start() => true;
|
||||
|
||||
public override ETaskResult Update()
|
||||
{
|
||||
if (!territoryData.TryGetContentFinderCondition(Task.ContentFinderConditionId,
|
||||
out var cfcData))
|
||||
throw new TaskException("Failed to get territory ID for content finder condition");
|
||||
|
||||
return clientState.TerritoryType != cfcData.TerritoryId
|
||||
? ETaskResult.TaskComplete
|
||||
: ETaskResult.StillRunning;
|
||||
}
|
||||
|
||||
public void StopNow() => bossModIpc.DisableAi();
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
internal sealed record DisableAi : ITask
|
||||
{
|
||||
public override string ToString() => "BossMod.DisableAi";
|
||||
}
|
||||
|
||||
internal sealed class DisableAiExecutor(
|
||||
BossModIpc bossModIpc) : TaskExecutor<DisableAi>
|
||||
{
|
||||
protected override bool Start()
|
||||
{
|
||||
bossModIpc.DisableAi();
|
||||
return true;
|
||||
}
|
||||
|
||||
public override ETaskResult Update() => ETaskResult.TaskComplete;
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
}
|
@ -53,7 +53,7 @@ internal static class WaitAtEnd
|
||||
return [new WaitNextStepOrSequence()];
|
||||
|
||||
case EInteractionType.Duty when !autoDutyIpc.IsConfiguredToRunContent(step.ContentFinderConditionId, step.AutoDutyEnabled):
|
||||
case EInteractionType.SinglePlayerDuty:
|
||||
case EInteractionType.SinglePlayerDuty when !step.BossModEnabled:
|
||||
return [new EndAutomation()];
|
||||
|
||||
case EInteractionType.WalkTo:
|
||||
|
@ -1,8 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Dalamud.Plugin.Services;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Questionable.Controller.Steps.Interactions;
|
||||
using Questionable.Data;
|
||||
using Questionable.Model;
|
||||
using Questionable.Model.Questing;
|
||||
|
||||
@ -11,11 +14,19 @@ namespace Questionable.Controller.Steps;
|
||||
internal sealed class TaskCreator
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly TerritoryData _territoryData;
|
||||
private readonly IClientState _clientState;
|
||||
private readonly ILogger<TaskCreator> _logger;
|
||||
|
||||
public TaskCreator(IServiceProvider serviceProvider, ILogger<TaskCreator> logger)
|
||||
public TaskCreator(
|
||||
IServiceProvider serviceProvider,
|
||||
TerritoryData territoryData,
|
||||
IClientState clientState,
|
||||
ILogger<TaskCreator> logger)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_territoryData = territoryData;
|
||||
_clientState = clientState;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@ -40,6 +51,31 @@ internal sealed class TaskCreator
|
||||
return tasks;
|
||||
})
|
||||
.ToList();
|
||||
|
||||
var singlePlayerDutyTask = newTasks
|
||||
.Where(y => y is SinglePlayerDuty.StartSinglePlayerDuty)
|
||||
.Cast<SinglePlayerDuty.StartSinglePlayerDuty>()
|
||||
.FirstOrDefault();
|
||||
if (singlePlayerDutyTask != null &&
|
||||
_territoryData.TryGetContentFinderCondition(singlePlayerDutyTask.ContentFinderConditionId,
|
||||
out var cfcData))
|
||||
{
|
||||
// if we have a single player duty in queue, we check if we're in the matching territory
|
||||
// if yes, skip all steps before (e.g. teleporting, waiting for navmesh, moving, interacting)
|
||||
if (_clientState.TerritoryType == cfcData.TerritoryId)
|
||||
{
|
||||
int index = newTasks.IndexOf(singlePlayerDutyTask);
|
||||
_logger.LogWarning(
|
||||
"Skipping {SkippedTaskCount} out of {TotalCount} tasks, questionable was started while in single player duty",
|
||||
index + 1, newTasks.Count);
|
||||
|
||||
newTasks.RemoveRange(0, index + 1);
|
||||
_logger.LogInformation("Next actual task: {NextTask}, total tasks left: {RemainingTaskCount}",
|
||||
newTasks.FirstOrDefault(),
|
||||
newTasks.Count);
|
||||
}
|
||||
}
|
||||
|
||||
if (newTasks.Count == 0)
|
||||
_logger.LogInformation("Nothing to execute for step?");
|
||||
else
|
||||
|
@ -45,7 +45,7 @@ internal sealed class TerritoryData
|
||||
.ToImmutableDictionary(x => x.Content.RowId, x => x.Name.ToDalamudString().ToString());
|
||||
|
||||
_contentFinderConditions = dataManager.GetExcelSheet<ContentFinderCondition>()
|
||||
.Where(x => x.RowId > 0 && x.Content.RowId != 0 && x.ContentLinkType == 1 && x.ContentType.RowId != 6)
|
||||
.Where(x => x.RowId > 0 && x.Content.RowId != 0 && x.ContentLinkType is 1 or 5 && x.ContentType.RowId != 6)
|
||||
.Select(x => new ContentFinderConditionData(x, dataManager.Language))
|
||||
.ToImmutableDictionary(x => x.ContentFinderConditionId, x => x);
|
||||
}
|
||||
|
73
Questionable/External/BossModIpc.cs
vendored
Normal file
73
Questionable/External/BossModIpc.cs
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
using Dalamud.Plugin.Ipc.Exceptions;
|
||||
using Dalamud.Plugin.Services;
|
||||
|
||||
namespace Questionable.External;
|
||||
|
||||
internal sealed class BossModIpc
|
||||
{
|
||||
private readonly ICommandManager _commandManager;
|
||||
private const string Name = "BossMod";
|
||||
|
||||
private readonly ICallGateSubscriber<string, string?> _getPreset;
|
||||
private readonly ICallGateSubscriber<string, bool, bool> _createPreset;
|
||||
private readonly ICallGateSubscriber<string, bool> _setPreset;
|
||||
private readonly ICallGateSubscriber<bool> _clearPreset;
|
||||
|
||||
public BossModIpc(IDalamudPluginInterface pluginInterface, ICommandManager commandManager)
|
||||
{
|
||||
_commandManager = commandManager;
|
||||
_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");
|
||||
}
|
||||
|
||||
public bool IsSupported()
|
||||
{
|
||||
try
|
||||
{
|
||||
return _getPreset.HasFunction;
|
||||
}
|
||||
catch (IpcError)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public string? GetPreset(string name)
|
||||
{
|
||||
return _getPreset.InvokeFunc(name);
|
||||
}
|
||||
|
||||
public bool CreatePreset(string name, bool overwrite)
|
||||
{
|
||||
return _createPreset.InvokeFunc(name, overwrite);
|
||||
}
|
||||
|
||||
public void SetPreset(string name)
|
||||
{
|
||||
_setPreset.InvokeFunc(name);
|
||||
}
|
||||
|
||||
public void ClearPreset()
|
||||
{
|
||||
_clearPreset.InvokeFunc();
|
||||
}
|
||||
|
||||
// TODO this should use your actual rotation plugin, not always vbm
|
||||
public void EnableAi(string presetName = "VBM Default")
|
||||
{
|
||||
_commandManager.ProcessCommand("/vbmai on");
|
||||
_commandManager.ProcessCommand("/vbm cfg ZoneModuleConfig EnableQuestBattles true");
|
||||
SetPreset(presetName);
|
||||
}
|
||||
|
||||
public void DisableAi()
|
||||
{
|
||||
_commandManager.ProcessCommand("/vbmai off");
|
||||
_commandManager.ProcessCommand("/vbm cfg ZoneModuleConfig EnableQuestBattles false");
|
||||
ClearPreset();
|
||||
}
|
||||
}
|
@ -131,6 +131,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
||||
serviceCollection.AddSingleton<NotificationMasterIpc>();
|
||||
serviceCollection.AddSingleton<AutomatonIpc>();
|
||||
serviceCollection.AddSingleton<AutoDutyIpc>();
|
||||
serviceCollection.AddSingleton<BossModIpc>();
|
||||
|
||||
serviceCollection.AddSingleton<GearStatsCalculator>();
|
||||
}
|
||||
@ -222,6 +223,14 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
||||
serviceCollection.AddTaskExecutor<InitiateLeve.Initiate, InitiateLeve.InitiateExecutor>();
|
||||
serviceCollection.AddTaskExecutor<InitiateLeve.SelectDifficulty, InitiateLeve.SelectDifficultyExecutor>();
|
||||
|
||||
serviceCollection.AddTaskFactory<SinglePlayerDuty.Factory>();
|
||||
serviceCollection
|
||||
.AddTaskExecutor<SinglePlayerDuty.StartSinglePlayerDuty, SinglePlayerDuty.StartSinglePlayerDutyExecutor>();
|
||||
serviceCollection.AddTaskExecutor<SinglePlayerDuty.EnableAi, SinglePlayerDuty.EnableAiExecutor>();
|
||||
serviceCollection
|
||||
.AddTaskExecutor<SinglePlayerDuty.WaitSinglePlayerDuty, SinglePlayerDuty.WaitSinglePlayerDutyExecutor>();
|
||||
serviceCollection.AddTaskExecutor<SinglePlayerDuty.DisableAi, SinglePlayerDuty.DisableAiExecutor>();
|
||||
|
||||
serviceCollection.AddTaskExecutor<WaitCondition.Task, WaitCondition.WaitConditionExecutor>();
|
||||
serviceCollection.AddTaskFactory<WaitAtEnd.Factory>();
|
||||
serviceCollection.AddTaskExecutor<WaitAtEnd.WaitDelay, WaitAtEnd.WaitDelayExecutor>();
|
||||
|
Loading…
x
Reference in New Issue
Block a user