Compare commits

..

No commits in common. "9bf3dbdf69913aa5311828aebfdf6c0067e7efc8" and "e3e5a401c3475b6631f9306e07ea600b21729f03" have entirely different histories.

38 changed files with 10270 additions and 13542 deletions

View file

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>FatePaths</AssemblyName>
<GenerateAssemblyInfo>False</GenerateAssemblyInfo>
<TargetFramework>netcoreapp1.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<LangVersion>12.0</LangVersion>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<None Remove="Questionable.FatePaths.FateDefinitionSchema" />
<EmbeddedResource Include="Questionable.FatePaths.FateDefinitionSchema" LogicalName="Questionable.FatePaths.FateDefinitionSchema" />
</ItemGroup>
<ItemGroup>
<Reference Include="Questionable.Model">
<HintPath>..\..\Questionable.Model.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View file

@ -1,177 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/WigglyMuffin/Questionable/raw/refs/heads/main/FatePaths/fatedefinition-v1.json",
"title": "FATE Definition V1",
"description": "A FATE farming definition",
"type": "object",
"properties": {
"$schema": {
"type": "string",
"const": "https://github.com/WigglyMuffin/Questionable/raw/refs/heads/main/FatePaths/fatedefinition-v1.json"
},
"Name": {
"description": "Display name of the FATE",
"type": "string"
},
"Description": {
"description": "Description of the FATE activity",
"type": "string"
},
"TerritoryId": {
"description": "Territory ID where the FATE takes place",
"type": "integer",
"minimum": 1
},
"Aetheryte": {
"description": "Nearest aetheryte for teleporting",
"$ref": "https://github.com/WigglyMuffin/Questionable/raw/refs/heads/main/Questionable.Model/common-aetheryte.json"
},
"Position": {
"description": "Position to navigate to for the FATE",
"$ref": "https://github.com/WigglyMuffin/Questionable/raw/refs/heads/main/Questionable.Model/common-vector3.json"
},
"Targets": {
"description": "List of FATE targets and actions to perform on them",
"type": "array",
"items": {
"type": "object",
"properties": {
"DataId": {
"type": "integer",
"minimum": 1
},
"Action": {
"type": "string"
}
},
"required": [
"DataId",
"Action"
],
"additionalProperties": false
},
"minItems": 1
},
"RequiredStatusId": {
"description": "Status effect required to participate in the FATE",
"type": "string"
},
"TransformNpcDataId": {
"description": "NPC to interact with to obtain the required status",
"type": "integer",
"minimum": 1
},
"TransformNpcPosition": {
"description": "Position of the transform NPC",
"$ref": "https://github.com/WigglyMuffin/Questionable/raw/refs/heads/main/Questionable.Model/common-vector3.json"
},
"EventExpiry": {
"description": "If this is a seasonal/event FATE, the date and time (in UTC) when it is no longer available. Date-only values are treated as ending at daily reset (14:59:59 UTC).",
"format": "date-time",
"type": [
"string",
"null"
]
},
"TransformDialogueChoices": {
"description": "Dialogue choices when interacting with the transform NPC",
"type": "array",
"items": {
"type": "object",
"properties": {
"Type": {
"type": "string",
"enum": [
"YesNo",
"List"
]
},
"ExcelSheet": {
"type": "string"
}
},
"required": [
"Type"
],
"allOf": [
{
"if": {
"properties": {
"Type": {
"const": "YesNo"
}
}
},
"then": {
"properties": {
"Prompt": {
"type": [
"string",
"integer"
]
},
"PromptIsRegularExpression": {
"type": "boolean"
},
"Yes": {
"type": "boolean",
"default": true
}
},
"required": [
"Prompt",
"Yes"
]
}
},
{
"if": {
"properties": {
"Type": {
"const": "List"
}
}
},
"then": {
"properties": {
"Prompt": {
"type": [
"string",
"integer",
"null"
]
},
"PromptIsRegularExpression": {
"type": "boolean"
},
"Answer": {
"type": [
"string",
"integer"
]
},
"AnswerIsRegularExpression": {
"type": "boolean"
}
},
"required": [
"Prompt",
"Answer"
]
}
}
]
}
}
},
"required": [
"$schema",
"Name",
"Description",
"TerritoryId",
"Aetheryte",
"Position",
"Targets"
],
"additionalProperties": false
}

View file

@ -1,109 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Numerics;
using System.Runtime.InteropServices;
using Questionable.Model.Common;
using Questionable.Model.Questing;
namespace Questionable.FatePaths;
public static class AssemblyFateDefinitionLoader
{
private static Dictionary<ushort, FateDefinition>? _definitions;
public static Stream FateDefinitionSchema => typeof(AssemblyFateDefinitionLoader).Assembly.GetManifestResourceStream("Questionable.FatePaths.FateDefinitionSchema");
public static IReadOnlyDictionary<ushort, FateDefinition> GetDefinitions()
{
if (_definitions == null)
{
_definitions = new Dictionary<ushort, FateDefinition>();
LoadDefinitions();
}
return _definitions ?? throw new InvalidOperationException("fate definition data is not initialized");
}
private static void AddDefinition(ushort id, FateDefinition definition)
{
_definitions[id] = definition;
}
private static void LoadDefinitions()
{
LoadDefinition0();
}
private static void LoadDefinition0()
{
FateDefinition obj = new FateDefinition
{
Name = "Little Ladies' Day (2026)",
Description = "Cheer Rhythm FATE in Ul'dah - Steps of Nald",
TerritoryId = 130,
Aetheryte = EAetheryteLocation.Uldah,
Position = new Vector3(-38.322124f, 3.9999998f, -144.23155f)
};
int num = 4;
List<FateActionTarget> list = new List<FateActionTarget>(num);
CollectionsMarshal.SetCount(list, num);
Span<FateActionTarget> span = CollectionsMarshal.AsSpan(list);
int num2 = 0;
span[num2] = new FateActionTarget
{
DataId = 18862u,
Action = EAction.CheerRhythmYellow
};
num2++;
span[num2] = new FateActionTarget
{
DataId = 18860u,
Action = EAction.CheerRhythmBlue
};
num2++;
span[num2] = new FateActionTarget
{
DataId = 18861u,
Action = EAction.CheerRhythmGreen
};
num2++;
span[num2] = new FateActionTarget
{
DataId = 18859u,
Action = EAction.CheerRhythmRed
};
obj.Targets = list;
obj.RequiredStatusId = EStatus.FaceInTheCrowd;
obj.TransformNpcDataId = 1055771u;
obj.TransformNpcPosition = new Vector3(-37.369385f, 5.0000005f, -130.14423f);
num2 = 3;
List<DialogueChoice> list2 = new List<DialogueChoice>(num2);
CollectionsMarshal.SetCount(list2, num2);
Span<DialogueChoice> span2 = CollectionsMarshal.AsSpan(list2);
num = 0;
span2[num] = new DialogueChoice
{
Type = EDialogChoiceType.List,
ExcelSheet = "custom/009/FesPdy2026FateDisguise_00951",
Prompt = new ExcelRef("TEXT_FESPDY2026FATEDISGUISE_00951_Q1_000_000"),
Answer = new ExcelRef("TEXT_FESPDY2026FATEDISGUISE_00951_A1_000_001")
};
num++;
span2[num] = new DialogueChoice
{
Type = EDialogChoiceType.List,
ExcelSheet = "custom/009/FesPdy2026FateDisguise_00951",
Prompt = new ExcelRef("TEXT_FESPDY2026FATEDISGUISE_00951_Q2_000_000"),
Answer = new ExcelRef("TEXT_FESPDY2026FATEDISGUISE_00951_A2_100_004")
};
num++;
span2[num] = new DialogueChoice
{
Type = EDialogChoiceType.YesNo,
ExcelSheet = "custom/009/FesPdy2026FateDisguise_00951",
Prompt = new ExcelRef("TEXT_FESPDY2026FATEDISGUISE_00951_CONFIRM_100_004")
};
obj.TransformDialogueChoices = list2;
AddDefinition(1, obj);
}
}

View file

@ -105,9 +105,6 @@
"type": "boolean", "type": "boolean",
"description": "Most interactions with objects are checked for a Y (height) difference of 2 in-game units. If set to true, the game won't attempt to get any closer if the height difference is larger than this." "description": "Most interactions with objects are checked for a Y (height) difference of 2 in-game units. If set to true, the game won't attempt to get any closer if the height difference is larger than this."
}, },
"IgnoreQuestMarker": {
"type": "boolean"
},
"RestartNavigationIfCancelled": { "RestartNavigationIfCancelled": {
"type": "boolean", "type": "boolean",
"description": "For some specific loading screen transitions (e.g. when entering/leaving the water through the portals in the ruby sea), setting this to 'false' means it won't re-attempt to move to the portal after the loading animation" "description": "For some specific loading screen transitions (e.g. when entering/leaving the water through the portals in the ruby sea), setting this to 'false' means it won't re-attempt to move to the portal after the loading animation"
@ -156,8 +153,7 @@
"Instruction", "Instruction",
"AcceptQuest", "AcceptQuest",
"CompleteQuest", "CompleteQuest",
"InitiateLeve", "InitiateLeve"
"FateAction"
] ]
}, },
"Disabled": { "Disabled": {
@ -794,34 +790,6 @@
"additionalProperties": false "additionalProperties": false
} }
}, },
"FateActionTargets": {
"description": "List of targets with per-target actions for FateAction steps",
"type": "array",
"items": {
"type": "object",
"properties": {
"DataId": {
"description": "The NPC data id to use the action on",
"type": "integer"
},
"Action": {
"description": "The action to use on this target",
"type": "string",
"enum": [
"Cheer Rhythm: Red",
"Cheer Rhythm: Blue",
"Cheer Rhythm: Green",
"Cheer Rhythm: Yellow"
]
}
},
"required": [
"DataId",
"Action"
],
"additionalProperties": false
}
},
"CombatItemUse": { "CombatItemUse": {
"description": "Unlike the 'AfterItemUse' condition that is used for spawning an enemy in the first place, interacting with an item at a certain stage of combat is required", "description": "Unlike the 'AfterItemUse' condition that is used for spawning an enemy in the first place, interacting with an item at a certain stage of combat is required",
"type": "object", "type": "object",
@ -1412,11 +1380,7 @@
"Shrouded Luminescence", "Shrouded Luminescence",
"Big Sneeze", "Big Sneeze",
"Trickster's Treat", "Trickster's Treat",
"Treater's Trick", "Treater's Trick"
"Cheer Rhythm: Red",
"Cheer Rhythm: Blue",
"Cheer Rhythm: Green",
"Cheer Rhythm: Yellow"
] ]
} }
}, },
@ -1425,20 +1389,6 @@
] ]
} }
}, },
{
"if": {
"properties": {
"InteractionType": {
"const": "FateAction"
}
}
},
"then": {
"required": [
"FateActionTargets"
]
}
},
{ {
"if": { "if": {
"properties": { "properties": {

File diff suppressed because it is too large Load diff

View file

@ -202,22 +202,6 @@ public sealed class ActionConverter : EnumConverter<EAction>
{ {
EAction.TreatersTrick, EAction.TreatersTrick,
"Treater's Trick" "Treater's Trick"
},
{
EAction.CheerRhythmRed,
"Cheer Rhythm: Red"
},
{
EAction.CheerRhythmBlue,
"Cheer Rhythm: Blue"
},
{
EAction.CheerRhythmGreen,
"Cheer Rhythm: Green"
},
{
EAction.CheerRhythmYellow,
"Cheer Rhythm: Yellow"
} }
}; };

View file

@ -126,10 +126,6 @@ public sealed class InteractionTypeConverter : EnumConverter<EInteractionType>
{ {
EInteractionType.CompleteQuest, EInteractionType.CompleteQuest,
"CompleteQuest" "CompleteQuest"
},
{
EInteractionType.FateAction,
"FateAction"
} }
}; };

View file

@ -5,17 +5,11 @@ namespace Questionable.Model.Questing.Converter;
public sealed class StatusConverter : EnumConverter<EStatus> public sealed class StatusConverter : EnumConverter<EStatus>
{ {
private static readonly Dictionary<EStatus, string> Values = new Dictionary<EStatus, string> private static readonly Dictionary<EStatus, string> Values = new Dictionary<EStatus, string> {
{ {
{ EStatus.Hidden,
EStatus.Hidden, "Hidden"
"Hidden" } };
},
{
EStatus.FaceInTheCrowd,
"FaceInTheCrowd"
}
};
public StatusConverter() public StatusConverter()
: base((IReadOnlyDictionary<EStatus, string>)Values) : base((IReadOnlyDictionary<EStatus, string>)Values)

View file

@ -62,10 +62,6 @@ public enum EAction
BigSneeze = 1765, BigSneeze = 1765,
TrickstersTreat = 44517, TrickstersTreat = 44517,
TreatersTrick = 44518, TreatersTrick = 44518,
CheerRhythmRed = 44501,
CheerRhythmBlue = 44502,
CheerRhythmGreen = 44503,
CheerRhythmYellow = 44504,
Prospect = 227, Prospect = 227,
CollectMiner = 240, CollectMiner = 240,
LuckOfTheMountaineer = 4081, LuckOfTheMountaineer = 4081,

View file

@ -35,6 +35,5 @@ public enum EInteractionType
UnlockTaxiStand, UnlockTaxiStand,
Instruction, Instruction,
AcceptQuest, AcceptQuest,
CompleteQuest, CompleteQuest
FateAction
} }

View file

@ -10,7 +10,6 @@ public enum EStatus : uint
GatheringRateUp = 218u, GatheringRateUp = 218u,
Prospect = 225u, Prospect = 225u,
Hidden = 614u, Hidden = 614u,
FaceInTheCrowd = 1494u,
Eukrasia = 2606u, Eukrasia = 2606u,
Jog = 4209u Jog = 4209u
} }

View file

@ -1,8 +0,0 @@
namespace Questionable.Model.Questing;
public sealed class FateActionTarget
{
public uint DataId { get; set; }
public EAction Action { get; set; }
}

View file

@ -1,35 +0,0 @@
using System;
using System.Collections.Generic;
using System.Numerics;
using System.Text.Json.Serialization;
using Questionable.Model.Common;
using Questionable.Model.Common.Converter;
namespace Questionable.Model.Questing;
public sealed class FateDefinition
{
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public ushort TerritoryId { get; set; }
public EAetheryteLocation Aetheryte { get; set; }
[JsonConverter(typeof(VectorConverter))]
public Vector3 Position { get; set; }
public List<FateActionTarget> Targets { get; set; } = new List<FateActionTarget>();
public EStatus? RequiredStatusId { get; set; }
public uint? TransformNpcDataId { get; set; }
[JsonConverter(typeof(VectorConverter))]
public Vector3? TransformNpcPosition { get; set; }
public List<DialogueChoice>? TransformDialogueChoices { get; set; }
public DateTime? EventExpiry { get; set; }
}

View file

@ -49,8 +49,6 @@ public sealed class QuestStep
public bool? RestartNavigationIfCancelled { get; set; } public bool? RestartNavigationIfCancelled { get; set; }
public bool IgnoreQuestMarker { get; set; }
public string? Comment { get; set; } public string? Comment { get; set; }
public EAetheryteLocation? Aetheryte { get; set; } public EAetheryteLocation? Aetheryte { get; set; }
@ -90,8 +88,6 @@ public sealed class QuestStep
public List<ComplexCombatData> ComplexCombatData { get; set; } = new List<ComplexCombatData>(); public List<ComplexCombatData> ComplexCombatData { get; set; } = new List<ComplexCombatData>();
public List<FateActionTarget> FateActionTargets { get; set; } = new List<FateActionTarget>();
public CombatItemUse? CombatItemUse { get; set; } public CombatItemUse? CombatItemUse { get; set; }
public float? CombatDelaySecondsAtStart { get; set; } public float? CombatDelaySecondsAtStart { get; set; }

View file

@ -97,12 +97,12 @@ internal sealed class CraftworksSupplyController : IDisposable
{ {
return; return;
} }
ushort blockedParentId = address->BlockedParentId; ushort contextMenuParentId = address->ContextMenuParentId;
if (blockedParentId == 0) if (contextMenuParentId == 0)
{ {
return; return;
} }
AtkUnitBase* addonById = AtkStage.Instance()->RaptureAtkUnitManager->GetAddonById(blockedParentId); AtkUnitBase* addonById = AtkStage.Instance()->RaptureAtkUnitManager->GetAddonById(contextMenuParentId);
if (addonById->NameString == "BankaCraftworksSupply") if (addonById->NameString == "BankaCraftworksSupply")
{ {
_logger.LogInformation("Picking item for {AddonName}", addonById->NameString); _logger.LogInformation("Picking item for {AddonName}", addonById->NameString);

View file

@ -61,8 +61,6 @@ internal sealed class InteractionUiController : IDisposable
private readonly ShopController _shopController; private readonly ShopController _shopController;
private readonly FateController _fateController;
private readonly BossModIpc _bossModIpc; private readonly BossModIpc _bossModIpc;
private readonly Configuration _configuration; private readonly Configuration _configuration;
@ -79,7 +77,7 @@ internal sealed class InteractionUiController : IDisposable
{ {
get get
{ {
if (!_isInitialCheck && !_questController.IsRunning && !_fateController.IsRunning) if (!_isInitialCheck && !_questController.IsRunning)
{ {
return _territoryData.IsQuestBattleInstance(_clientState.TerritoryType); return _territoryData.IsQuestBattleInstance(_clientState.TerritoryType);
} }
@ -87,7 +85,7 @@ internal sealed class InteractionUiController : IDisposable
} }
} }
public unsafe InteractionUiController(IAddonLifecycle addonLifecycle, IDataManager dataManager, QuestFunctions questFunctions, AetheryteFunctions aetheryteFunctions, ExcelFunctions excelFunctions, QuestController questController, GatheringPointRegistry gatheringPointRegistry, QuestRegistry questRegistry, QuestData questData, TerritoryData territoryData, IGameGui gameGui, ITargetManager targetManager, IPluginLog pluginLog, IClientState clientState, IObjectTable objectTable, ShopController shopController, FateController fateController, BossModIpc bossModIpc, Configuration configuration, ILogger<InteractionUiController> logger) public unsafe InteractionUiController(IAddonLifecycle addonLifecycle, IDataManager dataManager, QuestFunctions questFunctions, AetheryteFunctions aetheryteFunctions, ExcelFunctions excelFunctions, QuestController questController, GatheringPointRegistry gatheringPointRegistry, QuestRegistry questRegistry, QuestData questData, TerritoryData territoryData, IGameGui gameGui, ITargetManager targetManager, IPluginLog pluginLog, IClientState clientState, IObjectTable objectTable, ShopController shopController, BossModIpc bossModIpc, Configuration configuration, ILogger<InteractionUiController> logger)
{ {
_addonLifecycle = addonLifecycle; _addonLifecycle = addonLifecycle;
_dataManager = dataManager; _dataManager = dataManager;
@ -104,7 +102,6 @@ internal sealed class InteractionUiController : IDisposable
_clientState = clientState; _clientState = clientState;
_objectTable = objectTable; _objectTable = objectTable;
_shopController = shopController; _shopController = shopController;
_fateController = fateController;
_bossModIpc = bossModIpc; _bossModIpc = bossModIpc;
_configuration = configuration; _configuration = configuration;
_logger = logger; _logger = logger;
@ -457,15 +454,6 @@ internal sealed class InteractionUiController : IDisposable
} }
} }
} }
if (_fateController.IsRunning)
{
List<DialogueChoice> list4 = _fateController.CurrentFate?.TransformDialogueChoices;
if (list4 != null)
{
_logger.LogInformation("Adding {Count} dialogue choices from active FATE", list4.Count);
list.AddRange(list4.Select((DialogueChoice x) => new DialogueChoiceInfo(null, x)));
}
}
if (list.Count == 0) if (list.Count == 0)
{ {
_logger.LogDebug("No dialogue choices to check"); _logger.LogDebug("No dialogue choices to check");
@ -653,31 +641,12 @@ internal sealed class InteractionUiController : IDisposable
return; return;
} }
QuestController.QuestProgress simulatedQuest = _questController.SimulatedQuest; QuestController.QuestProgress simulatedQuest = _questController.SimulatedQuest;
if (simulatedQuest != null && HandleTravelYesNo(addonSelectYesno, simulatedQuest, text)) if (simulatedQuest == null || !HandleTravelYesNo(addonSelectYesno, simulatedQuest, text))
{ {
return; QuestController.QuestProgress nextQuest = _questController.NextQuest;
} if (nextQuest != null)
QuestController.QuestProgress nextQuest = _questController.NextQuest;
if ((nextQuest != null && CheckQuestYesNo(addonSelectYesno, nextQuest, text, checkAllSteps)) || !_fateController.IsRunning)
{
return;
}
List<DialogueChoice> list = _fateController.CurrentFate?.TransformDialogueChoices;
if (list == null)
{
return;
}
foreach (DialogueChoice item in list)
{
if (item.Type == EDialogChoiceType.YesNo)
{ {
StringOrRegex stringOrRegex = ResolveReference(null, item.ExcelSheet, item.Prompt, item.PromptIsRegularExpression); CheckQuestYesNo(addonSelectYesno, nextQuest, text, checkAllSteps);
if (stringOrRegex != null && IsMatch(text, stringOrRegex))
{
_logger.LogInformation("FATE: Returning {YesNo} for '{Prompt}'", item.Yes ? "Yes" : "No", text);
addonSelectYesno->AtkUnitBase.FireCallbackInt((!item.Yes) ? 1 : 0);
break;
}
} }
} }
} }

View file

@ -1,83 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Dalamud.Game.ClientState.Objects.Types;
using Microsoft.Extensions.Logging;
using Questionable.Controller.Steps.Common;
using Questionable.Functions;
using Questionable.Model;
using Questionable.Model.Questing;
namespace Questionable.Controller.Steps.Interactions;
internal static class FateAction
{
internal sealed class Factory : ITaskFactory
{
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
{
if (step.InteractionType != EInteractionType.FateAction)
{
return Array.Empty<ITask>();
}
if (step.FateActionTargets.Count == 0)
{
throw new InvalidOperationException("FateAction step requires FateActionTargets");
}
return new global::_003C_003Ez__ReadOnlyArray<ITask>(new ITask[2]
{
new Mount.UnmountTask(),
new UseOnTargets(step.FateActionTargets)
});
}
}
internal sealed record UseOnTargets(IList<FateActionTarget> Targets) : ITask
{
public bool ShouldRedoOnInterrupt()
{
return true;
}
public override string ToString()
{
return $"FateAction({Targets.Count} targets)";
}
}
internal sealed class UseOnTargetsExecutor(GameFunctions gameFunctions, ILogger<UseOnTargets> logger) : TaskExecutor<UseOnTargets>()
{
private DateTime _nextActionAt = DateTime.MinValue;
protected override bool Start()
{
logger.LogInformation("Starting FateAction: {Count} targets [{Targets}]", base.Task.Targets.Count, string.Join(", ", base.Task.Targets.Select((FateActionTarget t) => $"{t.DataId}→{t.Action}")));
return true;
}
public override ETaskResult Update()
{
if (DateTime.Now < _nextActionAt)
{
return ETaskResult.StillRunning;
}
foreach (FateActionTarget target in base.Task.Targets)
{
IGameObject gameObject = gameFunctions.FindObjectByDataId(target.DataId);
if (gameObject != null && gameObject.IsTargetable)
{
bool flag = gameFunctions.UseAction(gameObject, target.Action);
_nextActionAt = (flag ? DateTime.Now.AddSeconds(2.5) : DateTime.Now.AddSeconds(0.5));
return ETaskResult.StillRunning;
}
}
_nextActionAt = DateTime.Now.AddSeconds(0.25);
return ETaskResult.StillRunning;
}
public override bool ShouldInterruptOnDamage()
{
return false;
}
}
}

View file

@ -1,160 +0,0 @@
using System;
using System.Collections.Generic;
using Dalamud.Game.ClientState.Objects.Types;
using Microsoft.Extensions.Logging;
using Questionable.Functions;
using Questionable.Model.Questing;
namespace Questionable.Controller.Steps.Interactions;
internal static class FateFarming
{
internal sealed record WaitForFateTargets(IReadOnlyList<FateActionTarget> Targets) : ITask
{
public override string ToString()
{
return $"WaitForFateTargets({Targets.Count} targets)";
}
}
internal sealed class WaitForFateTargetsExecutor(GameFunctions gameFunctions, ILogger<WaitForFateTargetsExecutor> logger) : TaskExecutor<WaitForFateTargets>()
{
private DateTime _nextPollAt = DateTime.MinValue;
protected override bool Start()
{
logger.LogInformation("Waiting for FATE targets to appear ({Count} targets)", base.Task.Targets.Count);
return true;
}
public override ETaskResult Update()
{
if (DateTime.Now < _nextPollAt)
{
return ETaskResult.StillRunning;
}
foreach (FateActionTarget target in base.Task.Targets)
{
IGameObject gameObject = gameFunctions.FindObjectByDataId(target.DataId);
if (gameObject != null && gameObject.IsTargetable)
{
logger.LogInformation("FATE target {DataId} is now targetable", target.DataId);
return ETaskResult.TaskComplete;
}
}
_nextPollAt = DateTime.Now.AddSeconds(1.0);
return ETaskResult.StillRunning;
}
public override bool ShouldInterruptOnDamage()
{
return false;
}
}
internal sealed record SyncFateLevel : ITask
{
public override string ToString()
{
return "SyncFateLevel";
}
}
internal sealed class SyncFateLevelExecutor(GameFunctions gameFunctions, ILogger<SyncFateLevelExecutor> logger) : TaskExecutor<SyncFateLevel>()
{
protected override bool Start()
{
logger.LogInformation("Syncing to FATE level");
return true;
}
public override ETaskResult Update()
{
ushort currentFateId = gameFunctions.GetCurrentFateId();
if (currentFateId == 0)
{
logger.LogDebug("No active FATE to sync to, skipping");
return ETaskResult.TaskComplete;
}
gameFunctions.SyncToFate(currentFateId);
return ETaskResult.TaskComplete;
}
public override bool ShouldInterruptOnDamage()
{
return false;
}
}
internal sealed record FateActionLoop(IReadOnlyList<FateActionTarget> Targets) : ITask
{
public bool ShouldRedoOnInterrupt()
{
return true;
}
public override string ToString()
{
return $"FateActionLoop({Targets.Count} targets)";
}
}
internal sealed class FateActionLoopExecutor(GameFunctions gameFunctions, ILogger<FateActionLoopExecutor> logger) : TaskExecutor<FateActionLoop>()
{
private DateTime _nextActionAt = DateTime.MinValue;
private bool _fateWasActive;
protected override bool Start()
{
logger.LogInformation("Starting FATE action loop with {Count} targets", base.Task.Targets.Count);
_fateWasActive = gameFunctions.GetCurrentFateId() != 0;
return true;
}
public override ETaskResult Update()
{
if (DateTime.Now < _nextActionAt)
{
return ETaskResult.StillRunning;
}
bool flag = gameFunctions.GetCurrentFateId() != 0;
if (_fateWasActive && !flag)
{
bool flag2 = false;
foreach (FateActionTarget target in base.Task.Targets)
{
IGameObject gameObject = gameFunctions.FindObjectByDataId(target.DataId);
if (gameObject != null && gameObject.IsTargetable)
{
flag2 = true;
break;
}
}
if (!flag2)
{
logger.LogInformation("FATE completed (was active, now inactive, no targetable NPCs)");
return ETaskResult.TaskComplete;
}
}
_fateWasActive = flag;
foreach (FateActionTarget target2 in base.Task.Targets)
{
IGameObject gameObject2 = gameFunctions.FindObjectByDataId(target2.DataId);
if (gameObject2 != null && gameObject2.IsTargetable)
{
bool flag3 = gameFunctions.UseAction(gameObject2, target2.Action);
_nextActionAt = (flag3 ? DateTime.Now.AddSeconds(2.5) : DateTime.Now.AddSeconds(0.5));
return ETaskResult.StillRunning;
}
}
_nextActionAt = DateTime.Now.AddSeconds(0.25);
return ETaskResult.StillRunning;
}
public override bool ShouldInterruptOnDamage()
{
return false;
}
}
}

View file

@ -64,7 +64,7 @@ internal static class Interact
uint value = step.DataId.Value; uint value = step.DataId.Value;
EInteractionType interactionType2 = step.InteractionType; EInteractionType interactionType2 = step.InteractionType;
int skipMarkerCheck; int skipMarkerCheck;
if (!step.IgnoreQuestMarker && !step.TargetTerritoryId.HasValue && !(quest.Id is SatisfactionSupplyNpcId)) if (!step.TargetTerritoryId.HasValue && !(quest.Id is SatisfactionSupplyNpcId))
{ {
SkipConditions skipConditions = step.SkipConditions; SkipConditions skipConditions = step.SkipConditions;
if (skipConditions != null) if (skipConditions != null)
@ -72,22 +72,21 @@ internal static class Interact
SkipStepConditions stepIf = skipConditions.StepIf; SkipStepConditions stepIf = skipConditions.StepIf;
if (stepIf != null && stepIf.Never) if (stepIf != null && stepIf.Never)
{ {
goto IL_025f; goto IL_024f;
} }
} }
if (step.InteractionType != EInteractionType.PurchaseItem) if (step.InteractionType != EInteractionType.PurchaseItem)
{ {
skipMarkerCheck = ((step.DataId == 1052475) ? 1 : 0); skipMarkerCheck = ((step.DataId == 1052475) ? 1 : 0);
goto IL_0260; goto IL_0250;
} }
} }
goto IL_025f; goto IL_024f;
IL_0260: IL_024f:
yield return new Task(value, quest, interactionType2, (byte)skipMarkerCheck != 0, step.PickUpItemId ?? step.GCPurchase?.ItemId, step.TaxiStandId, step.SkipConditions?.StepIf, step.CompletionQuestVariablesFlags);
yield break;
IL_025f:
skipMarkerCheck = 1; skipMarkerCheck = 1;
goto IL_0260; goto IL_0250;
IL_0250:
yield return new Task(value, quest, interactionType2, (byte)skipMarkerCheck != 0, step.PickUpItemId ?? step.GCPurchase?.ItemId, step.TaxiStandId, step.SkipConditions?.StepIf, step.CompletionQuestVariablesFlags);
} }
} }
@ -107,13 +106,11 @@ internal static class Interact
public SkipStepConditions? SkipConditions { get; init; } public SkipStepConditions? SkipConditions { get; init; }
public EStatus? RequiredStatusId { get; init; }
public List<QuestWorkValue?> CompletionQuestVariablesFlags { get; } public List<QuestWorkValue?> CompletionQuestVariablesFlags { get; }
public bool HasCompletionQuestVariablesFlags { get; } public bool HasCompletionQuestVariablesFlags { get; }
public Task(uint DataId, Quest? Quest, EInteractionType InteractionType, bool SkipMarkerCheck = false, uint? PickUpItemId = null, byte? TaxiStandId = null, SkipStepConditions? SkipConditions = null, List<QuestWorkValue?>? CompletionQuestVariablesFlags = null, EStatus? RequiredStatusId = null) public Task(uint DataId, Quest? Quest, EInteractionType InteractionType, bool SkipMarkerCheck = false, uint? PickUpItemId = null, byte? TaxiStandId = null, SkipStepConditions? SkipConditions = null, List<QuestWorkValue?>? CompletionQuestVariablesFlags = null)
{ {
this.DataId = DataId; this.DataId = DataId;
this.Quest = Quest; this.Quest = Quest;
@ -122,7 +119,6 @@ internal static class Interact
this.PickUpItemId = PickUpItemId; this.PickUpItemId = PickUpItemId;
this.TaxiStandId = TaxiStandId; this.TaxiStandId = TaxiStandId;
this.SkipConditions = SkipConditions; this.SkipConditions = SkipConditions;
this.RequiredStatusId = RequiredStatusId;
this.CompletionQuestVariablesFlags = CompletionQuestVariablesFlags ?? new List<QuestWorkValue>(); this.CompletionQuestVariablesFlags = CompletionQuestVariablesFlags ?? new List<QuestWorkValue>();
HasCompletionQuestVariablesFlags = Quest != null && CompletionQuestVariablesFlags != null && QuestWorkUtils.HasCompletionFlags(CompletionQuestVariablesFlags); HasCompletionQuestVariablesFlags = Quest != null && CompletionQuestVariablesFlags != null && QuestWorkUtils.HasCompletionFlags(CompletionQuestVariablesFlags);
base._002Ector(); base._002Ector();
@ -139,7 +135,7 @@ internal static class Interact
} }
[CompilerGenerated] [CompilerGenerated]
public void Deconstruct(out uint DataId, out Quest? Quest, out EInteractionType InteractionType, out bool SkipMarkerCheck, out uint? PickUpItemId, out byte? TaxiStandId, out SkipStepConditions? SkipConditions, out List<QuestWorkValue?>? CompletionQuestVariablesFlags, out EStatus? RequiredStatusId) public void Deconstruct(out uint DataId, out Quest? Quest, out EInteractionType InteractionType, out bool SkipMarkerCheck, out uint? PickUpItemId, out byte? TaxiStandId, out SkipStepConditions? SkipConditions, out List<QuestWorkValue?>? CompletionQuestVariablesFlags)
{ {
DataId = this.DataId; DataId = this.DataId;
Quest = this.Quest; Quest = this.Quest;
@ -149,7 +145,6 @@ internal static class Interact
TaxiStandId = this.TaxiStandId; TaxiStandId = this.TaxiStandId;
SkipConditions = this.SkipConditions; SkipConditions = this.SkipConditions;
CompletionQuestVariablesFlags = this.CompletionQuestVariablesFlags; CompletionQuestVariablesFlags = this.CompletionQuestVariablesFlags;
RequiredStatusId = this.RequiredStatusId;
} }
} }
@ -228,20 +223,11 @@ internal static class Interact
} }
_needsUnmount = false; _needsUnmount = false;
} }
EStatus? requiredStatusId = base.Task.RequiredStatusId;
if (requiredStatusId.HasValue)
{
EStatus valueOrDefault = requiredStatusId.GetValueOrDefault();
if (gameFunctions.HasStatus(valueOrDefault))
{
return ETaskResult.TaskComplete;
}
}
uint? pickUpItemId = base.Task.PickUpItemId; uint? pickUpItemId = base.Task.PickUpItemId;
if (pickUpItemId.HasValue) if (pickUpItemId.HasValue)
{ {
uint valueOrDefault2 = pickUpItemId.GetValueOrDefault(); uint valueOrDefault = pickUpItemId.GetValueOrDefault();
if (InventoryManager.Instance()->GetInventoryItemCount(valueOrDefault2, isHq: false, checkEquipped: true, checkArmory: true, 0) > 0) if (InventoryManager.Instance()->GetInventoryItemCount(valueOrDefault, isHq: false, checkEquipped: true, checkArmory: true, 0) > 0)
{ {
return ETaskResult.TaskComplete; return ETaskResult.TaskComplete;
} }
@ -251,8 +237,8 @@ internal static class Interact
byte? taxiStandId = base.Task.TaxiStandId; byte? taxiStandId = base.Task.TaxiStandId;
if (taxiStandId.HasValue) if (taxiStandId.HasValue)
{ {
byte valueOrDefault3 = taxiStandId.GetValueOrDefault(); byte valueOrDefault2 = taxiStandId.GetValueOrDefault();
if (UIState.Instance()->IsChocoboTaxiStandUnlocked((uint)(valueOrDefault3 + 1179648))) if (UIState.Instance()->IsChocoboTaxiStandUnlocked((uint)(valueOrDefault2 + 1179648)))
{ {
return ETaskResult.TaskComplete; return ETaskResult.TaskComplete;
} }

View file

@ -53,20 +53,19 @@ internal static class WaitAtEnd
case EInteractionType.WaitForManualProgress: case EInteractionType.WaitForManualProgress:
case EInteractionType.Snipe: case EInteractionType.Snipe:
case EInteractionType.Instruction: case EInteractionType.Instruction:
case EInteractionType.FateAction:
return new global::_003C_003Ez__ReadOnlySingleElementList<ITask>(new WaitNextStepOrSequence()); return new global::_003C_003Ez__ReadOnlySingleElementList<ITask>(new WaitNextStepOrSequence());
case EInteractionType.Duty: case EInteractionType.Duty:
if (autoDutyIpc.IsConfiguredToRunContent(step.DutyOptions)) if (autoDutyIpc.IsConfiguredToRunContent(step.DutyOptions))
{ {
break; break;
} }
goto IL_01a1; goto IL_019d;
case EInteractionType.SinglePlayerDuty: case EInteractionType.SinglePlayerDuty:
if (bossModIpc.IsConfiguredToRunSoloInstance(quest.Id, step.SinglePlayerDutyOptions)) if (bossModIpc.IsConfiguredToRunSoloInstance(quest.Id, step.SinglePlayerDutyOptions))
{ {
break; break;
} }
goto IL_01a1; goto IL_019d;
case EInteractionType.WalkTo: case EInteractionType.WalkTo:
case EInteractionType.Jump: case EInteractionType.Jump:
return new global::_003C_003Ez__ReadOnlySingleElementList<ITask>(Next(quest, sequence)); return new global::_003C_003Ez__ReadOnlySingleElementList<ITask>(Next(quest, sequence));
@ -84,13 +83,13 @@ internal static class WaitAtEnd
{ {
break; break;
} }
goto IL_0288; goto IL_0284;
case EInteractionType.UseItem: case EInteractionType.UseItem:
if (!step.TargetTerritoryId.HasValue) if (!step.TargetTerritoryId.HasValue)
{ {
break; break;
} }
goto IL_0288; goto IL_0284;
case EInteractionType.AcceptQuest: case EInteractionType.AcceptQuest:
{ {
WaitQuestAccepted waitQuestAccepted = new WaitQuestAccepted(step.PickUpQuestId ?? quest.Id); WaitQuestAccepted waitQuestAccepted = new WaitQuestAccepted(step.PickUpQuestId ?? quest.Id);
@ -121,9 +120,9 @@ internal static class WaitAtEnd
} }
return new global::_003C_003Ez__ReadOnlyArray<ITask>(new ITask[2] { waitQuestCompleted, waitDelay2 }); return new global::_003C_003Ez__ReadOnlyArray<ITask>(new ITask[2] { waitQuestCompleted, waitDelay2 });
} }
IL_01a1: IL_019d:
return new global::_003C_003Ez__ReadOnlySingleElementList<ITask>(new EndAutomation()); return new global::_003C_003Ez__ReadOnlySingleElementList<ITask>(new EndAutomation());
IL_0288: IL_0284:
if (step.TerritoryId != step.TargetTerritoryId) if (step.TerritoryId != step.TargetTerritoryId)
{ {
task = new WaitCondition.Task(() => clientState.TerritoryType == step.TargetTerritoryId, "Wait(tp to territory: " + territoryData.GetNameAndId(step.TargetTerritoryId.Value) + ")"); task = new WaitCondition.Task(() => clientState.TerritoryType == step.TargetTerritoryId, "Wait(tp to territory: " + territoryData.GetNameAndId(step.TargetTerritoryId.Value) + ")");

View file

@ -34,10 +34,6 @@ internal sealed class CommandHandler : IDisposable
private readonly PriorityWindow _priorityWindow; private readonly PriorityWindow _priorityWindow;
private readonly FateController _fateController;
private readonly FateSelectionWindow _fateSelectionWindow;
private readonly ITargetManager _targetManager; private readonly ITargetManager _targetManager;
private readonly IClientState _clientState; private readonly IClientState _clientState;
@ -46,13 +42,12 @@ internal sealed class CommandHandler : IDisposable
private readonly ChangelogWindow _changelogWindow; private readonly ChangelogWindow _changelogWindow;
public CommandHandler(ICommandManager commandManager, IChatGui chatGui, QuestController questController, MovementController movementController, FateController fateController, QuestRegistry questRegistry, ConfigWindow configWindow, DebugOverlay debugOverlay, OneTimeSetupWindow oneTimeSetupWindow, QuestWindow questWindow, QuestSelectionWindow questSelectionWindow, QuestSequenceWindow questSequenceWindow, JournalProgressWindow journalProgressWindow, PriorityWindow priorityWindow, FateSelectionWindow fateSelectionWindow, ITargetManager targetManager, QuestFunctions questFunctions, GameFunctions gameFunctions, AetheryteFunctions aetheryteFunctions, IDataManager dataManager, IClientState clientState, IObjectTable objectTable, Configuration configuration, ChangelogWindow changelogWindow) public CommandHandler(ICommandManager commandManager, IChatGui chatGui, QuestController questController, MovementController movementController, QuestRegistry questRegistry, ConfigWindow configWindow, DebugOverlay debugOverlay, OneTimeSetupWindow oneTimeSetupWindow, QuestWindow questWindow, QuestSelectionWindow questSelectionWindow, QuestSequenceWindow questSequenceWindow, JournalProgressWindow journalProgressWindow, PriorityWindow priorityWindow, ITargetManager targetManager, QuestFunctions questFunctions, GameFunctions gameFunctions, AetheryteFunctions aetheryteFunctions, IDataManager dataManager, IClientState clientState, IObjectTable objectTable, Configuration configuration, ChangelogWindow changelogWindow)
{ {
_commandManager = commandManager; _commandManager = commandManager;
_chatGui = chatGui; _chatGui = chatGui;
_questController = questController; _questController = questController;
_movementController = movementController; _movementController = movementController;
_fateController = fateController;
_configWindow = configWindow; _configWindow = configWindow;
_oneTimeSetupWindow = oneTimeSetupWindow; _oneTimeSetupWindow = oneTimeSetupWindow;
_questWindow = questWindow; _questWindow = questWindow;
@ -60,7 +55,6 @@ internal sealed class CommandHandler : IDisposable
_questSequenceWindow = questSequenceWindow; _questSequenceWindow = questSequenceWindow;
_journalProgressWindow = journalProgressWindow; _journalProgressWindow = journalProgressWindow;
_priorityWindow = priorityWindow; _priorityWindow = priorityWindow;
_fateSelectionWindow = fateSelectionWindow;
_targetManager = targetManager; _targetManager = targetManager;
_clientState = clientState; _clientState = clientState;
_configuration = configuration; _configuration = configuration;
@ -99,7 +93,6 @@ internal sealed class CommandHandler : IDisposable
_chatGui.Print("/qst start - starts doing quests", "Questionable", 576); _chatGui.Print("/qst start - starts doing quests", "Questionable", 576);
_chatGui.Print("/qst stop - stops doing quests", "Questionable", 576); _chatGui.Print("/qst stop - stops doing quests", "Questionable", 576);
_chatGui.Print("/qst reload - reload all quest data", "Questionable", 576); _chatGui.Print("/qst reload - reload all quest data", "Questionable", 576);
_chatGui.Print("/qst fate - toggles the FATE farming window", "Questionable", 576);
break; break;
case "ha": case "ha":
case "help-all": case "help-all":
@ -116,7 +109,6 @@ internal sealed class CommandHandler : IDisposable
_chatGui.Print("/qst zone - shows all quests starting in the current zone (only includes quests with a known quest path, and currently visible unaccepted quests)", "Questionable", 576); _chatGui.Print("/qst zone - shows all quests starting in the current zone (only includes quests with a known quest path, and currently visible unaccepted quests)", "Questionable", 576);
_chatGui.Print("/qst journal - toggles the Journal Progress window", "Questionable", 576); _chatGui.Print("/qst journal - toggles the Journal Progress window", "Questionable", 576);
_chatGui.Print("/qst priority - toggles the Priority window", "Questionable", 576); _chatGui.Print("/qst priority - toggles the Priority window", "Questionable", 576);
_chatGui.Print("/qst fate - toggles the FATE farming window", "Questionable", 576);
_chatGui.Print("/qst handle-interrupt - makes Questionable handle queued interrupts immediately (useful if you manually start combat)", "Questionable", 576); _chatGui.Print("/qst handle-interrupt - makes Questionable handle queued interrupts immediately (useful if you manually start combat)", "Questionable", 576);
break; break;
case "c": case "c":
@ -134,7 +126,6 @@ internal sealed class CommandHandler : IDisposable
case "stop": case "stop":
_movementController.Stop(); _movementController.Stop();
_questController.Stop("Stop command"); _questController.Stop("Stop command");
_fateController.Stop("Stop command");
break; break;
case "reload": case "reload":
_questWindow.Reload(); _questWindow.Reload();
@ -154,10 +145,6 @@ internal sealed class CommandHandler : IDisposable
case "priority": case "priority":
_priorityWindow.ToggleOrUncollapse(); _priorityWindow.ToggleOrUncollapse();
break; break;
case "f":
case "fate":
_fateSelectionWindow.ToggleOrUncollapse();
break;
case "handle-interrupt": case "handle-interrupt":
_questController.InterruptQueueWithCombat(); _questController.InterruptQueueWithCombat();
break; break;

View file

@ -1,164 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.InteropServices;
using Dalamud.Plugin.Services;
using Microsoft.Extensions.Logging;
using Questionable.Controller.Steps;
using Questionable.Controller.Steps.Common;
using Questionable.Controller.Steps.Interactions;
using Questionable.Controller.Steps.Movement;
using Questionable.Controller.Steps.Shared;
using Questionable.Functions;
using Questionable.Model.Questing;
namespace Questionable.Controller;
internal sealed class FateController : MiniTaskController<FateController>
{
private readonly MovementController _movementController;
private readonly GameFunctions _gameFunctions;
private readonly IClientState _clientState;
private readonly ILogger<FateController> _logger;
private FateDefinition? _currentFate;
private int _completedCycles;
private int? _cycleLimit;
private DateTime _startTime;
public bool IsRunning => _currentFate != null;
public FateDefinition? CurrentFate => _currentFate;
public int CompletedCycles => _completedCycles;
public int? CycleLimit => _cycleLimit;
public TimeSpan ElapsedTime
{
get
{
if (!IsRunning)
{
return TimeSpan.Zero;
}
return DateTime.UtcNow - _startTime;
}
}
public FateController(IChatGui chatGui, ICondition condition, IServiceProvider serviceProvider, InterruptHandler interruptHandler, IDataManager dataManager, ILogger<FateController> logger, MovementController movementController, GameFunctions gameFunctions, IClientState clientState)
: base(chatGui, condition, serviceProvider, interruptHandler, dataManager, logger)
{
_movementController = movementController;
_gameFunctions = gameFunctions;
_clientState = clientState;
_logger = logger;
}
public void Start(FateDefinition fate, int? cycleLimit = null)
{
_currentFate = fate;
_completedCycles = 0;
_cycleLimit = cycleLimit;
_startTime = DateTime.UtcNow;
_logger.LogInformation("Starting FATE farming: {FateName} (limit: {Limit})", fate.Name, cycleLimit?.ToString(CultureInfo.InvariantCulture) ?? "unlimited");
EnqueueFateCycle();
}
public void Update()
{
if (_currentFate == null || _movementController.IsPathfinding || _movementController.IsPathRunning)
{
return;
}
if (_taskQueue.AllTasksComplete)
{
_completedCycles++;
if (_cycleLimit.HasValue && _completedCycles >= _cycleLimit.Value)
{
_logger.LogInformation("FATE cycle limit reached ({Cycles}/{Limit})", _completedCycles, _cycleLimit.Value);
Stop("Cycle limit reached");
return;
}
EnqueueFateCycle();
}
UpdateCurrentTask();
}
private void EnqueueFateCycle()
{
if (_currentFate != null)
{
_logger.LogInformation("Enqueuing FATE cycle for {FateName}", _currentFate.Name);
if (_clientState.TerritoryType != _currentFate.TerritoryId)
{
_taskQueue.Enqueue(new AetheryteShortcut.Task(null, null, _currentFate.Aetheryte, _currentFate.TerritoryId));
}
if (_currentFate.RequiredStatusId.HasValue && _currentFate.TransformNpcDataId.HasValue && _currentFate.TransformNpcPosition.HasValue && !_gameFunctions.HasStatus(_currentFate.RequiredStatusId.Value))
{
ILogger<FateController> logger = _logger;
object[] array = new object[1];
EStatus? requiredStatusId = _currentFate.RequiredStatusId;
array[0] = requiredStatusId.Value;
logger.LogInformation("Player missing required status {StatusId}, enqueuing transform", array);
_taskQueue.Enqueue(new MoveTask(_currentFate.TerritoryId, _currentFate.TransformNpcPosition.Value, null, 3f));
_taskQueue.Enqueue(new Mount.UnmountTask());
TaskQueue taskQueue = _taskQueue;
uint value = _currentFate.TransformNpcDataId.Value;
requiredStatusId = _currentFate.RequiredStatusId.Value;
taskQueue.Enqueue(new Interact.Task(value, null, EInteractionType.Interact, SkipMarkerCheck: true, null, null, null, null, requiredStatusId));
_taskQueue.Enqueue(new WaitAtEnd.WaitDelay(TimeSpan.FromSeconds(2L)));
}
_taskQueue.Enqueue(new MoveTask(_currentFate.TerritoryId, _currentFate.Position, null, 5f));
_taskQueue.Enqueue(new Mount.UnmountTask());
_taskQueue.Enqueue(new FateFarming.WaitForFateTargets(_currentFate.Targets));
_taskQueue.Enqueue(new FateFarming.SyncFateLevel());
_taskQueue.Enqueue(new FateFarming.FateActionLoop(_currentFate.Targets));
_taskQueue.Enqueue(new WaitAtEnd.WaitDelay(TimeSpan.FromSeconds(3L)));
}
}
public override void Stop(string label)
{
if (_currentFate != null)
{
_logger.LogInformation("Stopping FATE farming: {Label} (completed {Cycles} cycles)", label, _completedCycles);
_currentFate = null;
_completedCycles = 0;
_cycleLimit = null;
_taskQueue.Reset();
}
}
public override IList<string> GetRemainingTaskNames()
{
ITask task = _taskQueue.CurrentTaskExecutor?.CurrentTask;
if (task != null)
{
string text = task.ToString() ?? "?";
IList<string> remainingTaskNames = base.GetRemainingTaskNames();
int num = 1 + remainingTaskNames.Count;
List<string> list = new List<string>(num);
CollectionsMarshal.SetCount(list, num);
Span<string> span = CollectionsMarshal.AsSpan(list);
int num2 = 0;
span[num2] = text;
num2++;
{
foreach (string item in remainingTaskNames)
{
span[num2] = item;
num2++;
}
return list;
}
}
return base.GetRemainingTaskNames();
}
}

View file

@ -1,148 +0,0 @@
#define RELEASE
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.Json;
using Dalamud.Plugin;
using Microsoft.Extensions.Logging;
using Questionable.FatePaths;
using Questionable.Model.Questing;
using Questionable.Windows.QuestComponents;
namespace Questionable.Controller;
internal sealed class FateDefinitionRegistry
{
private readonly IDalamudPluginInterface _pluginInterface;
private readonly ILogger<FateDefinitionRegistry> _logger;
private readonly Dictionary<ushort, FateDefinition> _definitions = new Dictionary<ushort, FateDefinition>();
public IReadOnlyDictionary<ushort, FateDefinition> Definitions => _definitions;
public FateDefinitionRegistry(IDalamudPluginInterface pluginInterface, ILogger<FateDefinitionRegistry> logger)
{
_pluginInterface = pluginInterface;
_logger = logger;
Reload();
}
public void Reload()
{
_definitions.Clear();
LoadFromAssembly();
try
{
LoadFromDirectory(new DirectoryInfo(Path.Combine(_pluginInterface.ConfigDirectory.FullName, "FateDefinitions")));
}
catch (Exception exception)
{
_logger.LogError(exception, "Failed to load FATE definitions from user directory (some may have been successfully loaded)");
}
RemoveExpiredDefinitions();
_logger.LogInformation("Loaded {Count} FATE definitions in total", _definitions.Count);
}
[Conditional("RELEASE")]
private void LoadFromAssembly()
{
_logger.LogInformation("Loading FATE definitions from assembly");
IReadOnlyDictionary<ushort, FateDefinition> definitions = AssemblyFateDefinitionLoader.GetDefinitions();
_logger.LogInformation("AssemblyFateDefinitionLoader returned {Count} definitions", definitions.Count);
foreach (var (key, value) in definitions)
{
_definitions[key] = value;
}
_logger.LogInformation("Loaded {Count} FATE definitions from assembly", _definitions.Count);
}
[Conditional("DEBUG")]
private void LoadFromProjectDirectory()
{
DirectoryInfo directoryInfo = _pluginInterface.AssemblyLocation.Directory?.Parent?.Parent;
if (directoryInfo == null)
{
return;
}
DirectoryInfo directoryInfo2 = new DirectoryInfo(Path.Combine(directoryInfo.FullName, "FatePaths"));
if (directoryInfo2.Exists)
{
try
{
LoadFromDirectory(directoryInfo2);
}
catch (Exception exception)
{
_definitions.Clear();
_logger.LogError(exception, "Failed to load FATE definitions from project directory");
}
}
}
private void LoadFromDirectory(DirectoryInfo directory)
{
if (!directory.Exists)
{
_logger.LogInformation("Not loading FATE definitions from {DirectoryName} (doesn't exist)", directory);
return;
}
FileInfo[] files = directory.GetFiles("*.json");
foreach (FileInfo fileInfo in files)
{
try
{
ushort? num = ExtractIdFromName(fileInfo.Name);
if (!num.HasValue)
{
continue;
}
using FileStream utf8Json = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read);
FateDefinition fateDefinition = JsonSerializer.Deserialize<FateDefinition>(utf8Json);
if (fateDefinition != null)
{
_definitions[num.Value] = fateDefinition;
}
}
catch (Exception exception)
{
_logger.LogError(exception, "Unable to load FATE definition file {FileName}", fileInfo.FullName);
}
}
}
private void RemoveExpiredDefinitions()
{
foreach (ushort item in (from kvp in _definitions.Where<KeyValuePair<ushort, FateDefinition>>(delegate(KeyValuePair<ushort, FateDefinition> kvp)
{
DateTime? eventExpiry = kvp.Value.EventExpiry;
if (eventExpiry.HasValue)
{
DateTime valueOrDefault = eventExpiry.GetValueOrDefault();
return EventInfoComponent.NormalizeExpiry(valueOrDefault) < DateTime.UtcNow;
}
return false;
})
select kvp.Key).ToList())
{
_logger.LogInformation("Removing expired FATE definition {Id} '{Name}'", item, _definitions[item].Name);
_definitions.Remove(item);
}
}
private static ushort? ExtractIdFromName(string fileName)
{
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);
if (!fileNameWithoutExtension.Contains('_', StringComparison.Ordinal))
{
return null;
}
if (ushort.TryParse(fileNameWithoutExtension.Split('_', 2)[0], out var result))
{
return result;
}
return null;
}
}

View file

@ -99,8 +99,6 @@ internal sealed class QuestController : MiniTaskController<QuestController>
private readonly GatheringController _gatheringController; private readonly GatheringController _gatheringController;
private readonly FateController _fateController;
private readonly QuestRegistry _questRegistry; private readonly QuestRegistry _questRegistry;
private readonly JournalData _journalData; private readonly JournalData _journalData;
@ -246,7 +244,7 @@ internal sealed class QuestController : MiniTaskController<QuestController>
public event AutomationTypeChangedEventHandler? AutomationTypeChanged; public event AutomationTypeChangedEventHandler? AutomationTypeChanged;
public QuestController(IClientState clientState, IObjectTable objectTable, GameFunctions gameFunctions, QuestFunctions questFunctions, MovementController movementController, CombatController combatController, GatheringController gatheringController, FateController fateController, ILogger<QuestController> logger, QuestRegistry questRegistry, JournalData journalData, IKeyState keyState, IChatGui chatGui, ICondition condition, IToastGui toastGui, Configuration configuration, TaskCreator taskCreator, IServiceProvider serviceProvider, InterruptHandler interruptHandler, IDataManager dataManager, SinglePlayerDutyConfigComponent singlePlayerDutyConfigComponent, AutoDutyIpc autoDutyIpc, IDalamudPluginInterface pluginInterface) public QuestController(IClientState clientState, IObjectTable objectTable, GameFunctions gameFunctions, QuestFunctions questFunctions, MovementController movementController, CombatController combatController, GatheringController gatheringController, ILogger<QuestController> logger, QuestRegistry questRegistry, JournalData journalData, IKeyState keyState, IChatGui chatGui, ICondition condition, IToastGui toastGui, Configuration configuration, TaskCreator taskCreator, IServiceProvider serviceProvider, InterruptHandler interruptHandler, IDataManager dataManager, SinglePlayerDutyConfigComponent singlePlayerDutyConfigComponent, AutoDutyIpc autoDutyIpc, IDalamudPluginInterface pluginInterface)
: base(chatGui, condition, serviceProvider, interruptHandler, dataManager, logger) : base(chatGui, condition, serviceProvider, interruptHandler, dataManager, logger)
{ {
_clientState = clientState; _clientState = clientState;
@ -256,7 +254,6 @@ internal sealed class QuestController : MiniTaskController<QuestController>
_movementController = movementController; _movementController = movementController;
_combatController = combatController; _combatController = combatController;
_gatheringController = gatheringController; _gatheringController = gatheringController;
_fateController = fateController;
_questRegistry = questRegistry; _questRegistry = questRegistry;
_journalData = journalData; _journalData = journalData;
_keyState = keyState; _keyState = keyState;
@ -921,7 +918,6 @@ internal sealed class QuestController : MiniTaskController<QuestController>
_taskQueue.Reset(); _taskQueue.Reset();
_combatController.Stop("ClearTasksInternal"); _combatController.Stop("ClearTasksInternal");
_gatheringController.Stop("ClearTasksInternal"); _gatheringController.Stop("ClearTasksInternal");
_fateController.Stop("ClearTasksInternal");
} }
public override void Stop(string label) public override void Stop(string label)
@ -948,7 +944,6 @@ internal sealed class QuestController : MiniTaskController<QuestController>
_movementController.Stop(); _movementController.Stop();
_combatController.Stop(label); _combatController.Stop(label);
_gatheringController.Stop(label); _gatheringController.Stop(label);
_fateController.Stop(label);
} }
private void CheckNextTasks(string label) private void CheckNextTasks(string label)
@ -1247,7 +1242,6 @@ internal sealed class QuestController : MiniTaskController<QuestController>
_movementController.Stop(); _movementController.Stop();
_combatController.Stop("Execute next step"); _combatController.Stop("Execute next step");
_gatheringController.Stop("Execute next step"); _gatheringController.Stop("Execute next step");
_fateController.Stop("Execute next step");
try try
{ {
foreach (ITask item5 in _taskCreator.CreateTasks(CurrentQuest.Quest, CurrentQuest.Sequence, questSequence, step)) foreach (ITask item5 in _taskCreator.CreateTasks(CurrentQuest.Quest, CurrentQuest.Sequence, questSequence, step))

File diff suppressed because it is too large Load diff

View file

@ -404,7 +404,7 @@ internal sealed class QuestFunctions
_logger.LogTrace("GetMainScenarioQuest: scenarioTree->Data is null"); _logger.LogTrace("GetMainScenarioQuest: scenarioTree->Data is null");
return (QuestReference.NoQuest(MainScenarioQuestState.LoadingScreen), "Scenario Tree Data is null"); return (QuestReference.NoQuest(MainScenarioQuestState.LoadingScreen), "Scenario Tree Data is null");
} }
QuestId questId = new QuestId(ptr->Data->MainScenarioQuestIds[0]); QuestId questId = new QuestId(ptr->Data->CurrentScenarioQuest);
string item = $"sq: {questId}"; string item = $"sq: {questId}";
if (questId.Value == 0) if (questId.Value == 0)
{ {

View file

@ -32,8 +32,6 @@ internal sealed class ActiveQuestComponent
private readonly GatheringController _gatheringController; private readonly GatheringController _gatheringController;
private readonly FateController _fateController;
private readonly QuestFunctions _questFunctions; private readonly QuestFunctions _questFunctions;
private readonly ICommandManager _commandManager; private readonly ICommandManager _commandManager;
@ -59,19 +57,18 @@ internal sealed class ActiveQuestComponent
public event EventHandler? Reload; public event EventHandler? Reload;
[GeneratedRegex("\\s\\s+", RegexOptions.IgnoreCase, "en-US")] [GeneratedRegex("\\s\\s+", RegexOptions.IgnoreCase, "en-US")]
[GeneratedCode("System.Text.RegularExpressions.Generator", "10.0.14.7603")] [GeneratedCode("System.Text.RegularExpressions.Generator", "10.0.13.11305")]
private static Regex MultipleWhitespaceRegex() private static Regex MultipleWhitespaceRegex()
{ {
return _003CRegexGenerator_g_003EFBB8301322196CF81C64F1652C2FA6E1D6BF3907141F781E9D97ABED51BF056C4__MultipleWhitespaceRegex_0.Instance; return _003CRegexGenerator_g_003EFBB8301322196CF81C64F1652C2FA6E1D6BF3907141F781E9D97ABED51BF056C4__MultipleWhitespaceRegex_0.Instance;
} }
public ActiveQuestComponent(QuestController questController, MovementController movementController, CombatController combatController, GatheringController gatheringController, FateController fateController, QuestFunctions questFunctions, ICommandManager commandManager, Configuration configuration, QuestRegistry questRegistry, PriorityWindow priorityWindow, UiUtils uiUtils, IObjectTable objectTable, IClientState clientState, IChatGui chatGui, AutoDutyIpc autoDutyIpc, ILogger<ActiveQuestComponent> logger) public ActiveQuestComponent(QuestController questController, MovementController movementController, CombatController combatController, GatheringController gatheringController, QuestFunctions questFunctions, ICommandManager commandManager, Configuration configuration, QuestRegistry questRegistry, PriorityWindow priorityWindow, UiUtils uiUtils, IObjectTable objectTable, IClientState clientState, IChatGui chatGui, AutoDutyIpc autoDutyIpc, ILogger<ActiveQuestComponent> logger)
{ {
_questController = questController; _questController = questController;
_movementController = movementController; _movementController = movementController;
_combatController = combatController; _combatController = combatController;
_gatheringController = gatheringController; _gatheringController = gatheringController;
_fateController = fateController;
_questFunctions = questFunctions; _questFunctions = questFunctions;
_commandManager = commandManager; _commandManager = commandManager;
_configuration = configuration; _configuration = configuration;
@ -227,7 +224,6 @@ internal sealed class ActiveQuestComponent
_movementController.Stop(); _movementController.Stop();
_questController.Stop("Manual (no active quest)"); _questController.Stop("Manual (no active quest)");
_gatheringController.Stop("Manual (no active quest)"); _gatheringController.Stop("Manual (no active quest)");
_fateController.Stop("Manual (no active quest)");
if (!_autoDutyIpc.IsStopped()) if (!_autoDutyIpc.IsStopped())
{ {
try try
@ -588,7 +584,6 @@ internal sealed class ActiveQuestComponent
_movementController.Stop(); _movementController.Stop();
_questController.Stop("UI stop"); _questController.Stop("UI stop");
_gatheringController.Stop("UI stop"); _gatheringController.Stop("UI stop");
_fateController.Stop("UI stop");
} }
if (isMinimized) if (isMinimized)
{ {

View file

@ -351,7 +351,7 @@ internal sealed class EventInfoComponent
return new DateTime(date, new TimeOnly(14, 59, 59), DateTimeKind.Utc); return new DateTime(date, new TimeOnly(14, 59, 59), DateTimeKind.Utc);
} }
internal static DateTime NormalizeExpiry(DateTime d) private static DateTime NormalizeExpiry(DateTime d)
{ {
TimeSpan timeOfDay = d.TimeOfDay; TimeSpan timeOfDay = d.TimeOfDay;
TimeSpan timeSpan = new TimeSpan(23, 59, 59); TimeSpan timeSpan = new TimeSpan(23, 59, 59);
@ -366,7 +366,7 @@ internal sealed class EventInfoComponent
return d; return d;
} }
internal static string FormatRemainingDays(TimeSpan remaining) private static string FormatRemainingDays(TimeSpan remaining)
{ {
int num = (int)Math.Ceiling(Math.Max(0.0, remaining.TotalSeconds)); int num = (int)Math.Ceiling(Math.Max(0.0, remaining.TotalSeconds));
int num2 = num / 86400; int num2 = num / 86400;
@ -384,7 +384,7 @@ internal sealed class EventInfoComponent
return $"{value:D2}:{value2:D2}:{value3:D2}"; return $"{value:D2}:{value2:D2}:{value3:D2}";
} }
internal static string FormatRemainingFull(TimeSpan remaining) private static string FormatRemainingFull(TimeSpan remaining)
{ {
int num = (int)Math.Ceiling(Math.Max(0.0, remaining.TotalSeconds)); int num = (int)Math.Ceiling(Math.Max(0.0, remaining.TotalSeconds));
int num2 = num / 86400; int num2 = num / 86400;

View file

@ -10,18 +10,15 @@ internal sealed class RemainingTasksComponent
private readonly GatheringController _gatheringController; private readonly GatheringController _gatheringController;
private readonly FateController _fateController; public RemainingTasksComponent(QuestController questController, GatheringController gatheringController)
public RemainingTasksComponent(QuestController questController, GatheringController gatheringController, FateController fateController)
{ {
_questController = questController; _questController = questController;
_gatheringController = gatheringController; _gatheringController = gatheringController;
_fateController = fateController;
} }
public void Draw() public void Draw()
{ {
IList<string> remainingTaskNames = _fateController.GetRemainingTaskNames(); IList<string> remainingTaskNames = _gatheringController.GetRemainingTaskNames();
if (remainingTaskNames.Count > 0) if (remainingTaskNames.Count > 0)
{ {
ImGui.Separator(); ImGui.Separator();
@ -29,38 +26,23 @@ internal sealed class RemainingTasksComponent
foreach (string item in remainingTaskNames) foreach (string item in remainingTaskNames)
{ {
ImU8String text = new ImU8String(3, 1); ImU8String text = new ImU8String(3, 1);
text.AppendLiteral("F: "); text.AppendLiteral("G: ");
text.AppendFormatted(item); text.AppendFormatted(item);
ImGui.TextUnformatted(text); ImGui.TextUnformatted(text);
} }
ImGui.EndDisabled(); ImGui.EndDisabled();
return; return;
} }
IList<string> remainingTaskNames2 = _gatheringController.GetRemainingTaskNames(); IList<string> remainingTaskNames2 = _questController.GetRemainingTaskNames();
if (remainingTaskNames2.Count > 0) if (remainingTaskNames2.Count <= 0)
{
ImGui.Separator();
ImGui.BeginDisabled();
foreach (string item2 in remainingTaskNames2)
{
ImU8String text2 = new ImU8String(3, 1);
text2.AppendLiteral("G: ");
text2.AppendFormatted(item2);
ImGui.TextUnformatted(text2);
}
ImGui.EndDisabled();
return;
}
IList<string> remainingTaskNames3 = _questController.GetRemainingTaskNames();
if (remainingTaskNames3.Count <= 0)
{ {
return; return;
} }
ImGui.Separator(); ImGui.Separator();
ImGui.BeginDisabled(); ImGui.BeginDisabled();
foreach (string item3 in remainingTaskNames3) foreach (string item2 in remainingTaskNames2)
{ {
ImGui.TextUnformatted(item3); ImGui.TextUnformatted(item2);
} }
ImGui.EndDisabled(); ImGui.EndDisabled();
} }

View file

@ -1,681 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using Dalamud.Bindings.ImGui;
using Dalamud.Interface;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Components;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Questionable.Controller;
using Questionable.Data;
using Questionable.Functions;
using Questionable.Model;
using Questionable.Model.Questing;
namespace Questionable.Windows.QuestComponents;
internal sealed class SavedPresetsComponent
{
private sealed class PresetExportData
{
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public List<string> QuestIds { get; set; } = new List<string>();
}
private readonly QuestController _questController;
private readonly QuestFunctions _questFunctions;
private readonly QuestData _questData;
private readonly QuestRegistry _questRegistry;
private readonly Configuration _configuration;
private readonly IDalamudPluginInterface _pluginInterface;
private readonly IChatGui _chatGui;
private readonly UiUtils _uiUtils;
private readonly QuestTooltipComponent _questTooltipComponent;
private readonly ILogger<SavedPresetsComponent> _logger;
private string _newPresetName = string.Empty;
private string _newPresetDescription = string.Empty;
private bool _showSaveDialog;
private string? _presetToDelete;
private string? _expandedPreset;
private string? _renamingPresetKey;
private string _renamePresetName = string.Empty;
private string _renamePresetDescription = string.Empty;
private const string PresetClipboardPrefix = "qst:preset:";
private const string AllPresetsClipboardPrefix = "qst:presets:";
public SavedPresetsComponent(QuestController questController, QuestFunctions questFunctions, QuestData questData, QuestRegistry questRegistry, Configuration configuration, IDalamudPluginInterface pluginInterface, IChatGui chatGui, UiUtils uiUtils, QuestTooltipComponent questTooltipComponent, ILogger<SavedPresetsComponent> logger)
{
_questController = questController;
_questFunctions = questFunctions;
_questData = questData;
_questRegistry = questRegistry;
_configuration = configuration;
_pluginInterface = pluginInterface;
_chatGui = chatGui;
_uiUtils = uiUtils;
_questTooltipComponent = questTooltipComponent;
_logger = logger;
}
public void Draw()
{
ImGui.TextWrapped("Save your current priority queue as a preset for quick access later. Saved presets are stored in your configuration and persist between sessions.");
ImGui.Spacing();
DrawSaveSection();
ImGui.Spacing();
using (ImRaii.IEndObject endObject = ImRaii.Child("SavedPresetsList", new Vector2(-1f, -27f), border: true))
{
if (endObject)
{
DrawSavedPresets();
}
}
DrawBottomButtons();
}
private void DrawSaveSection()
{
int count = _questController.ManualPriorityQuests.Count;
if (_showSaveDialog)
{
ImGui.Text("Save Current Priority Queue as Preset:");
ImGui.SetNextItemWidth(200f);
ImGui.InputTextWithHint("##PresetName", "Preset name...", ref _newPresetName, 64);
ImGui.SameLine();
ImGui.SetNextItemWidth(250f);
ImGui.InputTextWithHint("##PresetDescription", "Description (optional)...", ref _newPresetDescription, 256);
ImGui.SameLine();
using (ImRaii.Disabled(string.IsNullOrWhiteSpace(_newPresetName) || count == 0))
{
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Save, "Save"))
{
SaveCurrentPreset();
}
}
ImGui.SameLine();
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Times, "Cancel"))
{
_showSaveDialog = false;
_newPresetName = string.Empty;
_newPresetDescription = string.Empty;
}
if (count == 0)
{
ImGui.TextColored(ImGuiColors.DalamudYellow, "Add quests to the priority queue first.");
}
return;
}
using (ImRaii.Disabled(count == 0))
{
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Plus, $"Save Current Queue ({count} quests)"))
{
_showSaveDialog = true;
}
}
if (count == 0 && ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
{
ImGui.SetTooltip("Add quests to the priority queue first to save them as a preset.");
}
}
private void DrawSavedPresets()
{
Dictionary<string, Configuration.SavedQuestPreset> savedPresets = _configuration.General.SavedPresets;
if (savedPresets.Count == 0)
{
ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudGrey);
ImGui.TextWrapped("No saved presets yet. Save your current priority queue using the button above.");
ImGui.PopStyleColor();
return;
}
foreach (var (key, preset) in savedPresets.OrderBy((KeyValuePair<string, Configuration.SavedQuestPreset> x) => x.Value.Name))
{
DrawPresetEntry(key, preset);
}
if (_presetToDelete != null)
{
if (savedPresets.Remove(_presetToDelete))
{
_pluginInterface.SavePluginConfig(_configuration);
_logger.LogInformation("Deleted saved preset '{PresetName}'", _presetToDelete);
}
_presetToDelete = null;
}
}
private void DrawPresetEntry(string key, Configuration.SavedQuestPreset preset)
{
using (ImRaii.PushId(key))
{
List<ElementId> availableQuests = GetAvailableQuests(preset.QuestIds);
List<ElementId> completedQuests = GetCompletedQuests(preset.QuestIds);
List<ElementId> alreadyPriorityQuests = GetAlreadyPriorityQuests(preset.QuestIds);
string text = preset.Name;
List<string> list = new List<string>();
if (availableQuests.Count > 0)
{
list.Add($"{availableQuests.Count} available");
}
if (alreadyPriorityQuests.Count > 0)
{
list.Add($"{alreadyPriorityQuests.Count} priority");
}
if (completedQuests.Count > 0)
{
list.Add($"{completedQuests.Count} completed");
}
if (list.Count > 0)
{
text = text + " (" + string.Join(", ", list) + ")";
}
bool flag = _expandedPreset == key;
ImU8String label = new ImU8String(3, 2);
label.AppendFormatted(text);
label.AppendLiteral("###");
label.AppendFormatted(key);
if (ImGui.CollapsingHeader(label, flag ? ImGuiTreeNodeFlags.DefaultOpen : ImGuiTreeNodeFlags.None))
{
_expandedPreset = key;
using (ImRaii.PushIndent())
{
if (_renamingPresetKey == key)
{
ImGui.Text("Name:");
ImGui.SameLine();
ImGui.SetNextItemWidth(300f);
ImGui.InputTextWithHint("##RenamePreset", "Preset name...", ref _renamePresetName, 64);
ImGui.Text("Description:");
ImGui.SameLine();
ImGui.SetNextItemWidth(300f);
ImGui.InputTextWithHint("##EditDescription", "Description (optional)...", ref _renamePresetDescription, 256);
using (ImRaii.Disabled(string.IsNullOrWhiteSpace(_renamePresetName)))
{
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Check, "Save Changes"))
{
RenamePreset(key, _renamePresetName, _renamePresetDescription);
}
}
ImGui.SameLine();
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Times, "Cancel"))
{
_renamingPresetKey = null;
_renamePresetName = string.Empty;
_renamePresetDescription = string.Empty;
}
}
else
{
if (!string.IsNullOrEmpty(preset.Description))
{
ImGui.TextWrapped(preset.Description);
}
Vector4 col = ImGuiColors.DalamudGrey;
ImU8String text2 = new ImU8String(26, 2);
text2.AppendLiteral("Created: ");
text2.AppendFormatted(preset.CreatedAt.ToLocalTime(), "g");
text2.AppendLiteral(" | Total quests: ");
text2.AppendFormatted(preset.QuestIds.Count);
ImGui.TextColored(in col, text2);
}
ImGui.Spacing();
using (ImRaii.Disabled(availableQuests.Count == 0))
{
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Plus, $"Add Available ({availableQuests.Count})"))
{
AddPresetToPriority(availableQuests);
}
}
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
{
if (availableQuests.Count == 0)
{
ImGui.SetTooltip("No available quests to add (all completed or already in priority).");
}
else
{
ImU8String tooltip = new ImU8String(44, 1);
tooltip.AppendLiteral("Add ");
tooltip.AppendFormatted(availableQuests.Count);
tooltip.AppendLiteral(" available quests to the priority queue.");
ImGui.SetTooltip(tooltip);
}
}
ImGui.SameLine();
using (ImRaii.Disabled(alreadyPriorityQuests.Count == 0))
{
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Minus, $"Remove from Priority ({alreadyPriorityQuests.Count})"))
{
RemovePresetFromPriority(alreadyPriorityQuests);
}
}
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
{
if (alreadyPriorityQuests.Count == 0)
{
ImGui.SetTooltip("No quests from this preset are in the priority queue.");
}
else
{
ImU8String tooltip2 = new ImU8String(39, 1);
tooltip2.AppendLiteral("Remove ");
tooltip2.AppendFormatted(alreadyPriorityQuests.Count);
tooltip2.AppendLiteral(" quests from the priority queue.");
ImGui.SetTooltip(tooltip2);
}
}
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Upload, "Export"))
{
ExportPresetToClipboard(preset);
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Export this preset to clipboard for sharing.");
}
ImGui.SameLine();
using (ImRaii.Disabled(_renamingPresetKey != null))
{
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Pen, "Edit"))
{
_renamingPresetKey = key;
_renamePresetName = preset.Name;
_renamePresetDescription = preset.Description;
}
}
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
{
ImGui.SetTooltip("Edit preset name and description.");
}
ImGui.SameLine();
int count = _questController.ManualPriorityQuests.Count;
using (ImRaii.Disabled(count == 0))
{
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Sync, "Update"))
{
UpdatePresetQuests(key, preset);
}
}
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
{
if (count == 0)
{
ImGui.SetTooltip("Add quests to the priority queue first.");
}
else
{
ImU8String tooltip3 = new ImU8String(71, 1);
tooltip3.AppendLiteral("Replace this preset's quests with the current priority queue (");
tooltip3.AppendFormatted(count);
tooltip3.AppendLiteral(" quests).");
ImGui.SetTooltip(tooltip3);
}
}
ImGui.SameLine();
using (ImRaii.Disabled(!ImGui.IsKeyDown(ImGuiKey.ModCtrl)))
{
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Trash, "Delete"))
{
_presetToDelete = key;
}
}
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
{
ImGui.SetTooltip("Hold CTRL to delete this preset.");
}
ImGui.Spacing();
ImGui.Separator();
foreach (ElementId item in availableQuests)
{
if (_questData.TryGetQuestInfo(item, out IQuestInfo questInfo) && _uiUtils.ChecklistItem(questInfo.Name ?? "", ImGuiColors.DalamudYellow, FontAwesomeIcon.Running))
{
_questTooltipComponent.Draw(questInfo);
}
}
foreach (ElementId item2 in alreadyPriorityQuests)
{
if (_questData.TryGetQuestInfo(item2, out IQuestInfo questInfo2) && _uiUtils.ChecklistItem(questInfo2.Name ?? "", ImGuiColors.DalamudYellow, FontAwesomeIcon.PersonWalkingArrowRight))
{
_questTooltipComponent.Draw(questInfo2);
}
}
foreach (ElementId item3 in completedQuests)
{
if (_questData.TryGetQuestInfo(item3, out IQuestInfo questInfo3) && _uiUtils.ChecklistItem(questInfo3.Name ?? "", ImGuiColors.ParsedGreen, FontAwesomeIcon.Check))
{
_questTooltipComponent.Draw(questInfo3);
}
}
foreach (ElementId unknownQuest in GetUnknownQuests(preset.QuestIds))
{
_uiUtils.ChecklistItem($"Unknown Quest ({unknownQuest})", ImGuiColors.DalamudGrey, FontAwesomeIcon.Question);
}
ImGui.Spacing();
}
}
else if (_expandedPreset == key)
{
_expandedPreset = null;
}
if (ImGui.IsItemHovered() && !string.IsNullOrEmpty(preset.Description))
{
ImGui.BeginTooltip();
ImGui.TextUnformatted(preset.Description);
ImGui.EndTooltip();
}
}
}
private void DrawBottomButtons()
{
PresetExportData presetExportData = ParseClipboardPreset();
List<PresetExportData> list = ParseClipboardAllPresets();
using (ImRaii.Disabled(presetExportData == null))
{
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Download, "Import Preset") && presetExportData != null)
{
ImportPresetFromClipboard(presetExportData);
}
}
if (presetExportData == null && ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
{
ImGui.SetTooltip("Copy a valid preset string to clipboard first.");
}
ImGui.SameLine();
using (ImRaii.Disabled(list == null || list.Count == 0))
{
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.FileImport, "Import All" + ((list != null && list.Count > 0) ? $" ({list.Count})" : "")) && list != null)
{
ImportAllPresetsFromClipboard(list);
}
}
if ((list == null || list.Count == 0) && ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
{
ImGui.SetTooltip("Copy a valid 'all presets' export string to clipboard first.");
}
ImGui.SameLine();
using (ImRaii.Disabled(_configuration.General.SavedPresets.Count == 0))
{
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.FileExport, $"Export All ({_configuration.General.SavedPresets.Count})"))
{
ExportAllPresetsToClipboard();
}
}
if (_configuration.General.SavedPresets.Count == 0 && ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
{
ImGui.SetTooltip("No saved presets to export.");
}
ImGui.SameLine();
using (ImRaii.Disabled(_configuration.General.SavedPresets.Count == 0 || !ImGui.IsKeyDown(ImGuiKey.ModCtrl)))
{
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Trash, "Clear All"))
{
_configuration.General.SavedPresets.Clear();
_pluginInterface.SavePluginConfig(_configuration);
_logger.LogInformation("Cleared all saved presets");
}
}
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
{
if (_configuration.General.SavedPresets.Count == 0)
{
ImGui.SetTooltip("No saved presets to clear.");
}
else
{
ImGui.SetTooltip("Hold CTRL to clear all saved presets.");
}
}
}
private void SaveCurrentPreset()
{
List<ElementId> list = _questController.ManualPriorityQuests.Select((Quest q) => q.Id).ToList();
string key = GeneratePresetKey(_newPresetName);
Configuration.SavedQuestPreset savedQuestPreset = new Configuration.SavedQuestPreset
{
Name = _newPresetName.Trim(),
Description = _newPresetDescription.Trim(),
QuestIds = list,
CreatedAt = DateTime.UtcNow
};
_configuration.General.SavedPresets[key] = savedQuestPreset;
_pluginInterface.SavePluginConfig(_configuration);
_logger.LogInformation("Saved preset '{PresetName}' with {Count} quests", savedQuestPreset.Name, list.Count);
_chatGui.Print($"Saved preset '{savedQuestPreset.Name}' with {list.Count} quests.", "Questionable", 576);
_newPresetName = string.Empty;
_newPresetDescription = string.Empty;
_showSaveDialog = false;
}
private string GeneratePresetKey(string name)
{
string text = "user_" + name.Trim().ToUpperInvariant().Replace(' ', '_');
string text2 = text;
int num = 1;
while (_configuration.General.SavedPresets.ContainsKey(text2))
{
text2 = $"{text}_{num}";
num++;
}
return text2;
}
private void ExportPresetToClipboard(Configuration.SavedQuestPreset preset)
{
string s = JsonConvert.SerializeObject(new PresetExportData
{
Name = preset.Name,
Description = preset.Description,
QuestIds = preset.QuestIds.Select((ElementId x) => x.ToString()).ToList()
});
ImGui.SetClipboardText("qst:preset:" + Convert.ToBase64String(Encoding.UTF8.GetBytes(s)));
_chatGui.Print("Exported preset '" + preset.Name + "' to clipboard.", "Questionable", 576);
}
private void ExportAllPresetsToClipboard()
{
List<PresetExportData> list = _configuration.General.SavedPresets.Values.Select((Configuration.SavedQuestPreset preset) => new PresetExportData
{
Name = preset.Name,
Description = preset.Description,
QuestIds = preset.QuestIds.Select((ElementId x) => x.ToString()).ToList()
}).ToList();
string s = JsonConvert.SerializeObject(list);
ImGui.SetClipboardText("qst:presets:" + Convert.ToBase64String(Encoding.UTF8.GetBytes(s)));
_chatGui.Print($"Exported {list.Count} presets to clipboard.", "Questionable", 576);
}
private static PresetExportData? ParseClipboardPreset()
{
try
{
string text = ImGui.GetClipboardText().Trim();
if (text.StartsWith("qst:preset:", StringComparison.InvariantCulture))
{
string text2 = text;
int length = "qst:preset:".Length;
string s = text2.Substring(length, text2.Length - length);
return JsonConvert.DeserializeObject<PresetExportData>(Encoding.UTF8.GetString(Convert.FromBase64String(s)));
}
}
catch (Exception)
{
}
return null;
}
private static List<PresetExportData>? ParseClipboardAllPresets()
{
try
{
string text = ImGui.GetClipboardText().Trim();
if (text.StartsWith("qst:presets:", StringComparison.InvariantCulture))
{
string text2 = text;
int length = "qst:presets:".Length;
string s = text2.Substring(length, text2.Length - length);
return JsonConvert.DeserializeObject<List<PresetExportData>>(Encoding.UTF8.GetString(Convert.FromBase64String(s)));
}
}
catch (Exception)
{
}
return null;
}
private void ImportPresetFromClipboard(PresetExportData exportData)
{
List<ElementId> list = exportData.QuestIds.Select((string id) => ElementId.FromString(id)).ToList();
string key = GeneratePresetKey(exportData.Name);
Configuration.SavedQuestPreset savedQuestPreset = new Configuration.SavedQuestPreset
{
Name = exportData.Name,
Description = exportData.Description,
QuestIds = list,
CreatedAt = DateTime.UtcNow
};
_configuration.General.SavedPresets[key] = savedQuestPreset;
_pluginInterface.SavePluginConfig(_configuration);
_logger.LogInformation("Imported preset '{PresetName}' with {Count} quests from clipboard", savedQuestPreset.Name, list.Count);
_chatGui.Print($"Imported preset '{savedQuestPreset.Name}' with {list.Count} quests.", "Questionable", 576);
}
private void ImportAllPresetsFromClipboard(List<PresetExportData> allExportData)
{
int num = 0;
foreach (PresetExportData allExportDatum in allExportData)
{
List<ElementId> questIds = allExportDatum.QuestIds.Select((string id) => ElementId.FromString(id)).ToList();
string key = GeneratePresetKey(allExportDatum.Name);
Configuration.SavedQuestPreset value = new Configuration.SavedQuestPreset
{
Name = allExportDatum.Name,
Description = allExportDatum.Description,
QuestIds = questIds,
CreatedAt = DateTime.UtcNow
};
_configuration.General.SavedPresets[key] = value;
num++;
}
_pluginInterface.SavePluginConfig(_configuration);
_logger.LogInformation("Imported {Count} presets from clipboard", num);
_chatGui.Print($"Imported {num} presets from clipboard.", "Questionable", 576);
}
private void AddPresetToPriority(List<ElementId> questIds)
{
int num = 0;
foreach (ElementId questId in questIds)
{
if (_questController.AddQuestPriority(questId))
{
num++;
}
}
if (num > 0)
{
_chatGui.Print($"Added {num} quests to priority queue.", "Questionable", 576);
}
_logger.LogInformation("Added {Count} quests from saved preset to priority list", num);
}
private void RemovePresetFromPriority(List<ElementId> questIds)
{
int num = 0;
foreach (ElementId questId in questIds)
{
Quest quest = _questController.ManualPriorityQuests.FirstOrDefault((Quest q) => q.Id.Equals(questId));
if (quest != null)
{
_questController.ManualPriorityQuests.Remove(quest);
num++;
}
}
if (num > 0)
{
_questController.SavePriorityQuests();
_chatGui.Print($"Removed {num} quests from priority queue.", "Questionable", 576);
_logger.LogInformation("Removed {Count} quests from priority list", num);
}
}
private void UpdatePresetQuests(string key, Configuration.SavedQuestPreset preset)
{
List<ElementId> list = _questController.ManualPriorityQuests.Select((Quest q) => q.Id).ToList();
int count = preset.QuestIds.Count;
preset.QuestIds = list;
_pluginInterface.SavePluginConfig(_configuration);
_logger.LogInformation("Updated preset '{PresetName}' from {OldCount} to {NewCount} quests", preset.Name, count, list.Count);
_chatGui.Print($"Updated preset '{preset.Name}' with {list.Count} quests (was {count}).", "Questionable", 576);
}
private void RenamePreset(string key, string newName, string newDescription)
{
if (_configuration.General.SavedPresets.TryGetValue(key, out Configuration.SavedQuestPreset value))
{
string name = value.Name;
value.Name = newName.Trim();
value.Description = newDescription.Trim();
_pluginInterface.SavePluginConfig(_configuration);
_logger.LogInformation("Updated preset '{OldName}' to '{NewName}'", name, value.Name);
}
_renamingPresetKey = null;
_renamePresetName = string.Empty;
_renamePresetDescription = string.Empty;
}
private List<ElementId> GetAvailableQuests(List<ElementId> questIds)
{
return (from questId in questIds
where _questFunctions.IsReadyToAcceptQuest(questId) || _questFunctions.IsQuestAccepted(questId)
where !_questController.ManualPriorityQuests.Any((Quest q) => q.Id.Equals(questId))
where _questRegistry.IsKnownQuest(questId)
select questId).ToList();
}
private List<ElementId> GetCompletedQuests(List<ElementId> questIds)
{
return questIds.Where((ElementId questId) => _questFunctions.IsQuestComplete(questId)).ToList();
}
private List<ElementId> GetAlreadyPriorityQuests(List<ElementId> questIds)
{
return (from questId in questIds
where _questController.ManualPriorityQuests.Any((Quest q) => q.Id.Equals(questId))
where !_questFunctions.IsQuestComplete(questId)
select questId).ToList();
}
private List<ElementId> GetUnknownQuests(List<ElementId> questIds)
{
IQuestInfo questInfo;
return questIds.Where((ElementId questId) => !_questData.TryGetQuestInfo(questId, out questInfo)).ToList();
}
}

View file

@ -1,401 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Dalamud.Bindings.ImGui;
using Dalamud.Interface;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Components;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Interface.Windowing;
using LLib.ImGui;
using Questionable.Controller;
using Questionable.Data;
using Questionable.Model.Questing;
using Questionable.Windows.QuestComponents;
namespace Questionable.Windows;
internal sealed class FateSelectionWindow : LWindow
{
private readonly FateController _fateController;
private readonly FateDefinitionRegistry _fateDefinitionRegistry;
private readonly QuestController _questController;
private readonly MovementController _movementController;
private readonly TerritoryData _territoryData;
private int _cycleLimit;
public FateSelectionWindow(FateController fateController, FateDefinitionRegistry fateDefinitionRegistry, QuestController questController, MovementController movementController, TerritoryData territoryData)
: base("FATE Farming###QuestionableFateFarming")
{
_fateController = fateController;
_fateDefinitionRegistry = fateDefinitionRegistry;
_questController = questController;
_movementController = movementController;
_territoryData = territoryData;
base.Size = new Vector2(600f, 400f);
base.SizeCondition = ImGuiCond.FirstUseEver;
base.SizeConstraints = new WindowSizeConstraints
{
MinimumSize = new Vector2(500f, 300f),
MaximumSize = new Vector2(900f, 700f)
};
}
public override void DrawContent()
{
if (_fateController.IsRunning)
{
DrawRunningHeader();
}
else
{
DrawControlsStrip();
}
if (_fateDefinitionRegistry.Definitions.Count == 0)
{
DrawEmptyState();
}
else
{
DrawFateTable();
}
}
private void DrawRunningHeader()
{
Vector2 cursorScreenPos = ImGui.GetCursorScreenPos();
float x = ImGui.GetContentRegionAvail().X;
float num = ImGui.GetTextLineHeightWithSpacing() * 3f + ImGui.GetStyle().ItemSpacing.Y * 3f;
ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList();
windowDrawList.AddRectFilledMultiColor(cursorScreenPos, cursorScreenPos + new Vector2(x, num), ImGui.ColorConvertFloat4ToU32(new Vector4(0.22f, 0.2f, 0.28f, 0.85f)), ImGui.ColorConvertFloat4ToU32(new Vector4(0.18f, 0.16f, 0.24f, 0.85f)), ImGui.ColorConvertFloat4ToU32(new Vector4(0.18f, 0.16f, 0.24f, 0.85f)), ImGui.ColorConvertFloat4ToU32(new Vector4(0.22f, 0.2f, 0.28f, 0.85f)));
windowDrawList.AddLine(cursorScreenPos + new Vector2(0f, num), cursorScreenPos + new Vector2(x, num), ImGui.ColorConvertFloat4ToU32(new Vector4(0.7f, 0.6f, 0.9f, 0.5f)), 2f);
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + ImGui.GetStyle().ItemSpacing.Y);
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + 8f);
float num2 = (float)ImGui.GetTime();
float num3 = 0.85f + MathF.Sin(num2 * 3f) * 0.15f;
Vector4 col = new Vector4(1f * num3, 0.85f * num3, 0f, 1f);
using (ImRaii.PushFont(UiBuilder.IconFont))
{
ImGui.TextColored(in col, FontAwesomeIcon.Star.ToIconString());
}
ImGui.SameLine();
ImGui.TextColored(ImGuiColors.ParsedGold, _fateController.CurrentFate.Name);
ImGui.SameLine(x - 35f);
using (ImRaii.PushColor(ImGuiCol.Button, Vector4.Zero))
{
using (ImRaii.PushColor(ImGuiCol.ButtonHovered, new Vector4(0.8f, 0.3f, 0.3f, 0.4f)))
{
using (ImRaii.PushColor(ImGuiCol.ButtonActive, new Vector4(0.9f, 0.2f, 0.2f, 0.6f)))
{
if (ImGuiComponents.IconButton(FontAwesomeIcon.Stop))
{
_fateController.Stop("UI stop");
_movementController.Stop();
}
}
}
}
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + 8f);
string value = (_fateController.CycleLimit.HasValue ? $"Cycle {_fateController.CompletedCycles + 1} / {_fateController.CycleLimit}" : $"Cycle {_fateController.CompletedCycles + 1}");
string value2 = FormatElapsed(_fateController.ElapsedTime);
IList<string> remainingTaskNames = _fateController.GetRemainingTaskNames();
string text = ((remainingTaskNames.Count > 0) ? remainingTaskNames.First() : "");
if (text.Length > 0)
{
Vector4 col2 = ImGuiColors.DalamudGrey3;
ImU8String text2 = new ImU8String(10, 3);
text2.AppendFormatted(value);
text2.AppendLiteral(" · ");
text2.AppendFormatted(value2);
text2.AppendLiteral(" · ");
text2.AppendFormatted(text);
ImGui.TextColored(in col2, text2);
}
else
{
Vector4 col2 = ImGuiColors.DalamudGrey3;
ImU8String text3 = new ImU8String(5, 2);
text3.AppendFormatted(value);
text3.AppendLiteral(" · ");
text3.AppendFormatted(value2);
ImGui.TextColored(in col2, text3);
}
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + 8f);
using (ImRaii.Disabled(disabled: true))
{
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted("Cycles:");
ImGui.SameLine();
ImGui.SetNextItemWidth(100f);
ImGui.InputInt("##CycleLimitRunning", ref _cycleLimit, 1, 5);
}
ImGui.SetCursorPosY(cursorScreenPos.Y + num - ImGui.GetCursorScreenPos().Y + ImGui.GetCursorPosY() + 4f);
ImGui.Spacing();
}
private void DrawControlsStrip()
{
using (ImRaii.Disabled(_fateController.IsRunning))
{
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted("Cycles:");
ImGui.SameLine();
ImGui.SetNextItemWidth(100f);
ImGui.InputInt("##CycleLimit", ref _cycleLimit, 1, 5);
if (_cycleLimit < 0)
{
_cycleLimit = 0;
}
ImGui.SameLine();
ImGui.TextColored(ImGuiColors.DalamudGrey, (_cycleLimit == 0) ? "(unlimited)" : "");
}
ImGui.Spacing();
}
private static void DrawEmptyState()
{
float y = ImGui.GetContentRegionAvail().Y;
float x = ImGui.GetContentRegionAvail().X;
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + y * 0.25f);
Vector4 col = new Vector4(0.6f, 0.5f, 0.8f, 0.7f);
Vector2 cursorScreenPos = ImGui.GetCursorScreenPos();
ImGui.PushFont(UiBuilder.IconFont);
string text = FontAwesomeIcon.Search.ToIconString();
Vector2 vector = ImGui.CalcTextSize(text);
vector *= 2.5f;
ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList();
Vector2 vector2 = new Vector2(x * 0.5f, 0f) + cursorScreenPos + new Vector2(0f, vector.Y * 0.5f);
for (int num = 3; num > 0; num--)
{
Vector4 col2 = new Vector4(col.X, col.Y, col.Z, col.W * 0.1f * (float)num);
ImGui.SetCursorScreenPos(vector2 - vector * 0.5f - new Vector2(num * 2, num * 2));
ImGui.TextColored(in col2, text);
}
ImGui.SetCursorScreenPos(vector2 - vector * 0.5f);
ImGui.TextColored(in col, text);
ImGui.PopFont();
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + vector.Y * 0.5f + 20f);
string text2 = "No FATE Definitions";
Vector2 vector3 = ImGui.CalcTextSize(text2);
Vector2 vector4 = new Vector2((x - vector3.X) * 0.5f, 0f) + ImGui.GetCursorScreenPos();
windowDrawList.AddText(vector4 + new Vector2(1f, 1f), ImGui.ColorConvertFloat4ToU32(new Vector4(0f, 0f, 0f, 0.5f)), text2);
ImGui.SetCursorPosX((x - vector3.X) * 0.5f);
ImGui.TextColored(new Vector4(0.95f, 0.95f, 1f, 1f), text2);
ImGui.Spacing();
ImGui.Spacing();
string text3 = "Add FATE definitions to the FatePaths folder to get started.";
ImGui.SetCursorPosX((x - ImGui.CalcTextSize(text3).X) * 0.5f);
ImGui.TextColored(new Vector4(0.7f, 0.7f, 0.8f, 1f), text3);
}
private void DrawFateTable()
{
List<FateDefinition> list = _fateDefinitionRegistry.Definitions.Values.OrderBy(delegate(FateDefinition f)
{
DateTime? eventExpiry = f.EventExpiry;
if (eventExpiry.HasValue)
{
DateTime valueOrDefault = eventExpiry.GetValueOrDefault();
if (EventInfoComponent.NormalizeExpiry(valueOrDefault) - DateTime.UtcNow > TimeSpan.Zero)
{
return 0;
}
}
return 1;
}).ThenBy(delegate(FateDefinition f)
{
DateTime? eventExpiry = f.EventExpiry;
if (eventExpiry.HasValue)
{
DateTime valueOrDefault = eventExpiry.GetValueOrDefault();
TimeSpan timeSpan = EventInfoComponent.NormalizeExpiry(valueOrDefault) - DateTime.UtcNow;
if (timeSpan > TimeSpan.Zero)
{
return timeSpan.TotalSeconds;
}
}
return double.MaxValue;
}).ThenBy<FateDefinition, string>((FateDefinition f) => f.Name, StringComparer.OrdinalIgnoreCase)
.ToList();
using ImRaii.IEndObject endObject = ImRaii.Table("FateTable", 4, ImGuiTableFlags.SizingStretchProp | ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersInnerH | ImGuiTableFlags.ScrollY);
if (!endObject)
{
return;
}
ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.None, 3f);
ImGui.TableSetupColumn("Zone", ImGuiTableColumnFlags.None, 2f);
ImGui.TableSetupColumn("Expiry", ImGuiTableColumnFlags.WidthFixed, 80f);
ImGui.TableSetupColumn("##Actions", ImGuiTableColumnFlags.WidthFixed, 30f);
ImGui.TableHeadersRow();
foreach (FateDefinition item in list)
{
ImGui.TableNextRow();
bool flag = _fateController.IsRunning && _fateController.CurrentFate == item;
if (flag)
{
float num = (float)ImGui.GetTime();
float w = 0.1f + MathF.Sin(num * 2.5f) * 0.05f;
ImGui.TableSetBgColor(ImGuiTableBgTarget.RowBg1, ImGui.GetColorU32(new Vector4(1f, 0.85f, 0f, w)));
}
ImGui.TableNextColumn();
DrawFateRowName(item, flag);
ImGui.TableNextColumn();
ImGui.TextUnformatted(_territoryData.GetName(item.TerritoryId) ?? item.Description);
ImGui.TableNextColumn();
DrawFateRowExpiry(item);
ImGui.TableNextColumn();
bool disabled = _fateController.IsRunning || _questController.AutomationType != QuestController.EAutomationType.Manual;
DrawFateRowActions(item, disabled);
}
}
private void DrawFateRowName(FateDefinition fate, bool isActive)
{
if (isActive)
{
float num = (float)ImGui.GetTime();
float num2 = 0.85f + MathF.Sin(num * 3f) * 0.15f;
ImGui.TextColored(new Vector4(1f * num2, 0.85f * num2, 0f, 1f), fate.Name);
}
else
{
ImGui.TextUnformatted(fate.Name);
}
if (!ImGui.IsItemHovered())
{
return;
}
using (ImRaii.Tooltip())
{
ImGui.TextColored(ImGuiColors.DalamudWhite, fate.Name);
ImGui.Separator();
ImGui.PushTextWrapPos(300f);
ImGui.TextUnformatted(fate.Description);
ImGui.PopTextWrapPos();
ImGui.Spacing();
string nameAndId = _territoryData.GetNameAndId(fate.TerritoryId);
Vector4 col = ImGuiColors.DalamudGrey;
ImU8String text = new ImU8String(6, 1);
text.AppendLiteral("Zone: ");
text.AppendFormatted(nameAndId);
ImGui.TextColored(in col, text);
col = ImGuiColors.DalamudGrey;
ImU8String text2 = new ImU8String(9, 1);
text2.AppendLiteral("Targets: ");
text2.AppendFormatted(fate.Targets.Count);
ImGui.TextColored(in col, text2);
if (fate.RequiredStatusId.HasValue)
{
ImGui.TextColored(ImGuiColors.DalamudYellow, "Requires transformation");
}
DateTime? eventExpiry = fate.EventExpiry;
if (eventExpiry.HasValue)
{
DateTime valueOrDefault = eventExpiry.GetValueOrDefault();
TimeSpan timeSpan = EventInfoComponent.NormalizeExpiry(valueOrDefault) - DateTime.UtcNow;
if (timeSpan > TimeSpan.Zero)
{
string text3 = EventInfoComponent.FormatRemainingFull(timeSpan);
ImGui.TextColored(ImGuiColors.DalamudOrange, text3);
}
}
}
}
private static void DrawFateRowExpiry(FateDefinition fate)
{
DateTime? eventExpiry = fate.EventExpiry;
if (eventExpiry.HasValue)
{
DateTime valueOrDefault = eventExpiry.GetValueOrDefault();
TimeSpan timeSpan = EventInfoComponent.NormalizeExpiry(valueOrDefault) - DateTime.UtcNow;
if (timeSpan > TimeSpan.Zero)
{
string text = EventInfoComponent.FormatRemainingDays(timeSpan);
ImGui.TextColored((timeSpan.TotalDays < 3.0) ? ImGuiColors.DalamudOrange : ImGuiColors.DalamudGrey, text);
}
else
{
ImGui.TextColored(ImGuiColors.DalamudGrey3, "Expired");
}
}
else
{
ImGui.TextColored(ImGuiColors.DalamudGrey3, "--");
}
}
private void DrawFateRowActions(FateDefinition fate, bool disabled)
{
using (ImRaii.Disabled(disabled))
{
ImU8String id = new ImU8String(5, 1);
id.AppendLiteral("fate_");
id.AppendFormatted(fate.Name);
using (ImRaii.PushId(id))
{
if (ImGuiComponents.IconButton(FontAwesomeIcon.Play))
{
_questController.Stop("FATE farming start");
_movementController.Stop();
int? cycleLimit = ((_cycleLimit > 0) ? new int?(_cycleLimit) : ((int?)null));
_fateController.Start(fate, cycleLimit);
}
}
}
if (disabled && ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
{
if (_fateController.IsRunning)
{
ImGui.SetTooltip("Already farming a FATE");
}
else
{
ImGui.SetTooltip("Stop quest automation first");
}
}
}
private static string FormatElapsed(TimeSpan elapsed)
{
IFormatProvider invariantCulture;
if (elapsed.TotalHours >= 1.0)
{
invariantCulture = CultureInfo.InvariantCulture;
IFormatProvider provider = invariantCulture;
DefaultInterpolatedStringHandler handler = new DefaultInterpolatedStringHandler(5, 3, invariantCulture);
handler.AppendFormatted((int)elapsed.TotalHours);
handler.AppendLiteral("h ");
handler.AppendFormatted(elapsed.Minutes, "D2");
handler.AppendLiteral("m ");
handler.AppendFormatted(elapsed.Seconds, "D2");
handler.AppendLiteral("s");
return string.Create(provider, ref handler);
}
if (elapsed.TotalMinutes >= 1.0)
{
invariantCulture = CultureInfo.InvariantCulture;
IFormatProvider provider2 = invariantCulture;
DefaultInterpolatedStringHandler handler2 = new DefaultInterpolatedStringHandler(3, 2, invariantCulture);
handler2.AppendFormatted((int)elapsed.TotalMinutes);
handler2.AppendLiteral("m ");
handler2.AppendFormatted(elapsed.Seconds, "D2");
handler2.AppendLiteral("s");
return string.Create(provider2, ref handler2);
}
invariantCulture = CultureInfo.InvariantCulture;
IFormatProvider provider3 = invariantCulture;
DefaultInterpolatedStringHandler handler3 = new DefaultInterpolatedStringHandler(1, 1, invariantCulture);
handler3.AppendFormatted(elapsed.Seconds);
handler3.AppendLiteral("s");
return string.Create(provider3, ref handler3);
}
}

View file

@ -28,14 +28,11 @@ internal sealed class PriorityWindow : LWindow
private readonly PresetBuilderComponent _presetBuilderComponent; private readonly PresetBuilderComponent _presetBuilderComponent;
private readonly SavedPresetsComponent _savedPresetsComponent; public PriorityWindow(QuestController questController, QuestFunctions questFunctions, QuestSelector questSelector, QuestTooltipComponent questTooltipComponent, PresetBuilderComponent presetBuilderComponent, UiUtils uiUtils, IChatGui chatGui, IDalamudPluginInterface pluginInterface)
public PriorityWindow(QuestController questController, QuestFunctions questFunctions, QuestSelector questSelector, QuestTooltipComponent questTooltipComponent, PresetBuilderComponent presetBuilderComponent, SavedPresetsComponent savedPresetsComponent, UiUtils uiUtils, IChatGui chatGui, IDalamudPluginInterface pluginInterface)
: base("Quest Priority###QuestionableQuestPriority") : base("Quest Priority###QuestionableQuestPriority")
{ {
_manualPriorityComponent = new ManualPriorityComponent(questController, questFunctions, questSelector, questTooltipComponent, uiUtils, chatGui, pluginInterface); _manualPriorityComponent = new ManualPriorityComponent(questController, questFunctions, questSelector, questTooltipComponent, uiUtils, chatGui, pluginInterface);
_presetBuilderComponent = presetBuilderComponent; _presetBuilderComponent = presetBuilderComponent;
_savedPresetsComponent = savedPresetsComponent;
base.Size = new Vector2(500f, 500f); base.Size = new Vector2(500f, 500f);
base.SizeCondition = ImGuiCond.Once; base.SizeCondition = ImGuiCond.Once;
base.SizeConstraints = new WindowSizeConstraints base.SizeConstraints = new WindowSizeConstraints
@ -59,17 +56,10 @@ internal sealed class PriorityWindow : LWindow
_manualPriorityComponent.Draw(); _manualPriorityComponent.Draw();
} }
} }
using (ImRaii.IEndObject endObject3 = ImRaii.TabItem("Quest Presets")) using ImRaii.IEndObject endObject3 = ImRaii.TabItem("Quest Presets");
if (endObject3)
{ {
if (endObject3) _presetBuilderComponent.Draw();
{
_presetBuilderComponent.Draw();
}
}
using ImRaii.IEndObject endObject4 = ImRaii.TabItem("Saved Presets");
if (endObject4)
{
_savedPresetsComponent.Draw();
} }
} }

View file

@ -68,9 +68,6 @@
<Reference Include="QuestPaths"> <Reference Include="QuestPaths">
<HintPath>..\..\QuestPaths.dll</HintPath> <HintPath>..\..\QuestPaths.dll</HintPath>
</Reference> </Reference>
<Reference Include="FatePaths">
<HintPath>..\..\FatePaths.dll</HintPath>
</Reference>
<Reference Include="GatheringPaths"> <Reference Include="GatheringPaths">
<HintPath>..\..\GatheringPaths.dll</HintPath> <HintPath>..\..\GatheringPaths.dll</HintPath>
</Reference> </Reference>

View file

@ -61,20 +61,6 @@ internal sealed class Configuration : IPluginConfiguration
[JsonProperty(ItemConverterType = typeof(ElementIdNConverter))] [JsonProperty(ItemConverterType = typeof(ElementIdNConverter))]
public List<ElementId> PriorityQuests { get; set; } = new List<ElementId>(); public List<ElementId> PriorityQuests { get; set; } = new List<ElementId>();
public Dictionary<string, SavedQuestPreset> SavedPresets { get; set; } = new Dictionary<string, SavedQuestPreset>();
}
internal sealed class SavedQuestPreset
{
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
[JsonProperty(ItemConverterType = typeof(ElementIdNConverter))]
public List<ElementId> QuestIds { get; set; } = new List<ElementId>();
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
} }
internal sealed class StopConfiguration internal sealed class StopConfiguration

View file

@ -33,19 +33,16 @@ internal sealed class DalamudInitializer : IDisposable
private readonly Configuration _configuration; private readonly Configuration _configuration;
private readonly FateController _fateController;
private readonly PartyWatchdog _partyWatchdog; private readonly PartyWatchdog _partyWatchdog;
private readonly ILogger<DalamudInitializer> _logger; private readonly ILogger<DalamudInitializer> _logger;
public DalamudInitializer(IDalamudPluginInterface pluginInterface, IFramework framework, QuestController questController, MovementController movementController, FateController fateController, WindowSystem windowSystem, OneTimeSetupWindow oneTimeSetupWindow, QuestWindow questWindow, DebugOverlay debugOverlay, ConfigWindow configWindow, QuestSelectionWindow questSelectionWindow, QuestSequenceWindow questSequenceWindow, QuestValidationWindow questValidationWindow, JournalProgressWindow journalProgressWindow, PriorityWindow priorityWindow, FateSelectionWindow fateSelectionWindow, ChangelogWindow changelogWindow, IToastGui toastGui, Configuration configuration, PartyWatchdog partyWatchdog, ILogger<DalamudInitializer> logger) public DalamudInitializer(IDalamudPluginInterface pluginInterface, IFramework framework, QuestController questController, MovementController movementController, WindowSystem windowSystem, OneTimeSetupWindow oneTimeSetupWindow, QuestWindow questWindow, DebugOverlay debugOverlay, ConfigWindow configWindow, QuestSelectionWindow questSelectionWindow, QuestSequenceWindow questSequenceWindow, QuestValidationWindow questValidationWindow, JournalProgressWindow journalProgressWindow, PriorityWindow priorityWindow, ChangelogWindow changelogWindow, IToastGui toastGui, Configuration configuration, PartyWatchdog partyWatchdog, ILogger<DalamudInitializer> logger)
{ {
_pluginInterface = pluginInterface; _pluginInterface = pluginInterface;
_framework = framework; _framework = framework;
_questController = questController; _questController = questController;
_movementController = movementController; _movementController = movementController;
_fateController = fateController;
_windowSystem = windowSystem; _windowSystem = windowSystem;
_oneTimeSetupWindow = oneTimeSetupWindow; _oneTimeSetupWindow = oneTimeSetupWindow;
_questWindow = questWindow; _questWindow = questWindow;
@ -63,7 +60,6 @@ internal sealed class DalamudInitializer : IDisposable
_windowSystem.AddWindow(questValidationWindow); _windowSystem.AddWindow(questValidationWindow);
_windowSystem.AddWindow(journalProgressWindow); _windowSystem.AddWindow(journalProgressWindow);
_windowSystem.AddWindow(priorityWindow); _windowSystem.AddWindow(priorityWindow);
_windowSystem.AddWindow(fateSelectionWindow);
_windowSystem.AddWindow(changelogWindow); _windowSystem.AddWindow(changelogWindow);
_pluginInterface.UiBuilder.Draw += _windowSystem.Draw; _pluginInterface.UiBuilder.Draw += _windowSystem.Draw;
_pluginInterface.UiBuilder.OpenMainUi += ToggleQuestWindow; _pluginInterface.UiBuilder.OpenMainUi += ToggleQuestWindow;
@ -78,7 +74,6 @@ internal sealed class DalamudInitializer : IDisposable
{ {
_partyWatchdog.Update(); _partyWatchdog.Update();
_questController.Update(); _questController.Update();
_fateController.Update();
try try
{ {
_movementController.Update(); _movementController.Update();
@ -86,7 +81,6 @@ internal sealed class DalamudInitializer : IDisposable
catch (MovementController.PathfindingFailedException) catch (MovementController.PathfindingFailedException)
{ {
_questController.Stop("Pathfinding failed"); _questController.Stop("Pathfinding failed");
_fateController.Stop("Pathfinding failed");
} }
} }

View file

@ -168,10 +168,6 @@ public sealed class QuestionablePlugin : IDalamudPlugin, IDisposable
serviceCollection.AddTaskFactoryAndExecutor<Questionable.Controller.Steps.Interactions.Action.UseOnObject, Questionable.Controller.Steps.Interactions.Action.Factory, Questionable.Controller.Steps.Interactions.Action.UseOnObjectExecutor>(); serviceCollection.AddTaskFactoryAndExecutor<Questionable.Controller.Steps.Interactions.Action.UseOnObject, Questionable.Controller.Steps.Interactions.Action.Factory, Questionable.Controller.Steps.Interactions.Action.UseOnObjectExecutor>();
serviceCollection.AddTaskExecutor<Questionable.Controller.Steps.Interactions.Action.UseMudraOnObject, Questionable.Controller.Steps.Interactions.Action.UseMudraOnObjectExecutor>(); serviceCollection.AddTaskExecutor<Questionable.Controller.Steps.Interactions.Action.UseMudraOnObject, Questionable.Controller.Steps.Interactions.Action.UseMudraOnObjectExecutor>();
serviceCollection.AddTaskExecutor<Questionable.Controller.Steps.Interactions.Action.TriggerStatusIfMissing, Questionable.Controller.Steps.Interactions.Action.TriggerStatusIfMissingExecutor>(); serviceCollection.AddTaskExecutor<Questionable.Controller.Steps.Interactions.Action.TriggerStatusIfMissing, Questionable.Controller.Steps.Interactions.Action.TriggerStatusIfMissingExecutor>();
serviceCollection.AddTaskFactoryAndExecutor<FateAction.UseOnTargets, FateAction.Factory, FateAction.UseOnTargetsExecutor>();
serviceCollection.AddTaskExecutor<FateFarming.WaitForFateTargets, FateFarming.WaitForFateTargetsExecutor>();
serviceCollection.AddTaskExecutor<FateFarming.SyncFateLevel, FateFarming.SyncFateLevelExecutor>();
serviceCollection.AddTaskExecutor<FateFarming.FateActionLoop, FateFarming.FateActionLoopExecutor>();
serviceCollection.AddTaskFactoryAndExecutor<StatusOff.Task, StatusOff.Factory, StatusOff.DoStatusOff>(); serviceCollection.AddTaskFactoryAndExecutor<StatusOff.Task, StatusOff.Factory, StatusOff.DoStatusOff>();
serviceCollection.AddTaskFactoryAndExecutor<Interact.Task, Interact.Factory, Interact.DoInteract>(); serviceCollection.AddTaskFactoryAndExecutor<Interact.Task, Interact.Factory, Interact.DoInteract>();
serviceCollection.AddTaskFactory<Jump.Factory>(); serviceCollection.AddTaskFactory<Jump.Factory>();
@ -214,13 +210,11 @@ public sealed class QuestionablePlugin : IDalamudPlugin, IDisposable
{ {
serviceCollection.AddSingleton<MovementController>(); serviceCollection.AddSingleton<MovementController>();
serviceCollection.AddSingleton<MovementOverrideController>(); serviceCollection.AddSingleton<MovementOverrideController>();
serviceCollection.AddSingleton<FateDefinitionRegistry>();
serviceCollection.AddSingleton<GatheringPointRegistry>(); serviceCollection.AddSingleton<GatheringPointRegistry>();
serviceCollection.AddSingleton<QuestRegistry>(); serviceCollection.AddSingleton<QuestRegistry>();
serviceCollection.AddSingleton<QuestController>(); serviceCollection.AddSingleton<QuestController>();
serviceCollection.AddSingleton<CombatController>(); serviceCollection.AddSingleton<CombatController>();
serviceCollection.AddSingleton<GatheringController>(); serviceCollection.AddSingleton<GatheringController>();
serviceCollection.AddSingleton<FateController>();
serviceCollection.AddSingleton<ContextMenuController>(); serviceCollection.AddSingleton<ContextMenuController>();
serviceCollection.AddSingleton<ShopController>(); serviceCollection.AddSingleton<ShopController>();
serviceCollection.AddSingleton<InterruptHandler>(); serviceCollection.AddSingleton<InterruptHandler>();
@ -252,7 +246,6 @@ public sealed class QuestionablePlugin : IDalamudPlugin, IDisposable
serviceCollection.AddSingleton<EventInfoComponent>(); serviceCollection.AddSingleton<EventInfoComponent>();
serviceCollection.AddSingleton<ManualPriorityComponent>(); serviceCollection.AddSingleton<ManualPriorityComponent>();
serviceCollection.AddSingleton<PresetBuilderComponent>(); serviceCollection.AddSingleton<PresetBuilderComponent>();
serviceCollection.AddSingleton<SavedPresetsComponent>();
serviceCollection.AddSingleton<QuestTooltipComponent>(); serviceCollection.AddSingleton<QuestTooltipComponent>();
serviceCollection.AddSingleton<QuickAccessButtonsComponent>(); serviceCollection.AddSingleton<QuickAccessButtonsComponent>();
serviceCollection.AddSingleton<QuestValidationComponent>(); serviceCollection.AddSingleton<QuestValidationComponent>();
@ -272,7 +265,6 @@ public sealed class QuestionablePlugin : IDalamudPlugin, IDisposable
serviceCollection.AddSingleton<QuestValidationWindow>(); serviceCollection.AddSingleton<QuestValidationWindow>();
serviceCollection.AddSingleton<JournalProgressWindow>(); serviceCollection.AddSingleton<JournalProgressWindow>();
serviceCollection.AddSingleton<PriorityWindow>(); serviceCollection.AddSingleton<PriorityWindow>();
serviceCollection.AddSingleton<FateSelectionWindow>();
serviceCollection.AddSingleton<GeneralConfigComponent>(); serviceCollection.AddSingleton<GeneralConfigComponent>();
serviceCollection.AddSingleton<PluginConfigComponent>(); serviceCollection.AddSingleton<PluginConfigComponent>();
serviceCollection.AddSingleton<DutyConfigComponent>(); serviceCollection.AddSingleton<DutyConfigComponent>();

View file

@ -3,7 +3,7 @@ using System.Runtime.CompilerServices;
namespace System.Text.RegularExpressions.Generated; namespace System.Text.RegularExpressions.Generated;
[GeneratedCode("System.Text.RegularExpressions.Generator", "10.0.14.7603")] [GeneratedCode("System.Text.RegularExpressions.Generator", "10.0.13.11305")]
[SkipLocalsInit] [SkipLocalsInit]
internal sealed class _003CRegexGenerator_g_003EFBB8301322196CF81C64F1652C2FA6E1D6BF3907141F781E9D97ABED51BF056C4__MultipleWhitespaceRegex_0 : Regex internal sealed class _003CRegexGenerator_g_003EFBB8301322196CF81C64F1652C2FA6E1D6BF3907141F781E9D97ABED51BF056C4__MultipleWhitespaceRegex_0 : Regex
{ {

View file

@ -3,7 +3,7 @@ using System.CodeDom.Compiler;
namespace System.Text.RegularExpressions.Generated; namespace System.Text.RegularExpressions.Generated;
[GeneratedCode("System.Text.RegularExpressions.Generator", "10.0.14.7603")] [GeneratedCode("System.Text.RegularExpressions.Generator", "10.0.13.11305")]
internal static class _003CRegexGenerator_g_003EFBB8301322196CF81C64F1652C2FA6E1D6BF3907141F781E9D97ABED51BF056C4__Utilities internal static class _003CRegexGenerator_g_003EFBB8301322196CF81C64F1652C2FA6E1D6BF3907141F781E9D97ABED51BF056C4__Utilities
{ {
internal static readonly TimeSpan s_defaultTimeout = ((AppContext.GetData("REGEX_DEFAULT_MATCH_TIMEOUT") is TimeSpan timeSpan) ? timeSpan : Regex.InfiniteMatchTimeout); internal static readonly TimeSpan s_defaultTimeout = ((AppContext.GetData("REGEX_DEFAULT_MATCH_TIMEOUT") is TimeSpan timeSpan) ? timeSpan : Regex.InfiniteMatchTimeout);