"TerritoryId": 156,
"InteractionType": "Interact",
"AetheryteShortcut": "Mor Dhona",
- "TargetTerritoryId": 351
+ "TargetTerritoryId": 351,
+ "SkipConditions": {
+ "AetheryteShortcutIf": {
+ "InTerritory": [
+ 351
+ ]
+ },
+ "StepIf": {
+ "InTerritory": [
+ 351
+ ]
+ }
+ }
},
{
"DataId": 1032081,
"TerritoryId": 351,
"InteractionType": "SinglePlayerDuty",
"Comment": "Estinien vs. Arch Ultima",
- "DialogueChoices": [
- {
- "Type": "YesNo",
- "Prompt": "TEXT_LUCKMG110_03682_Q1_100_125",
- "Yes": true
- }
- ]
+ "BossModEnabled": false,
+ "BossModNotes": [
+ "AI doesn't move automatically for the first boss",
+ "AI doesn't move automatically for the dialogue with gaius on the bridge",
+ "After walking downstairs automatically, AI tries to run back towards the stairs (ignoring the arena boudnary)",
+ "After moving from the arena boundary, AI doesn't move into melee range and stops too far away when initially attacking"
+ ],
+ "$.1": "This doesn't have a duty confirmation dialog, so we're treating TEXT_LUCKMG110_03682_Q1_100_125 as one"
}
]
},
using Microsoft.Extensions.Logging;
using Questionable.Controller.Steps.Interactions;
using Questionable.Data;
+using Questionable.External;
using Questionable.Functions;
using Questionable.Model;
using Questionable.Model.Gathering;
private readonly ITargetManager _targetManager;
private readonly IClientState _clientState;
private readonly ShopController _shopController;
+ private readonly BossModIpc _bossModIpc;
private readonly ILogger<InteractionUiController> _logger;
private readonly Regex _returnRegex;
private readonly Regex _purchaseItemRegex;
IPluginLog pluginLog,
IClientState clientState,
ShopController shopController,
+ BossModIpc bossModIpc,
ILogger<InteractionUiController> logger)
{
_addonLifecycle = addonLifecycle;
_targetManager = targetManager;
_clientState = clientState;
_shopController = shopController;
+ _bossModIpc = bossModIpc;
_logger = logger;
_returnRegex = _dataManager.GetExcelSheet<Addon>().GetRow(196).GetRegex(addon => addon.Text, pluginLog)!;
int? answer = HandleListChoice(actualPrompt, answers, checkAllSteps) ?? HandleInstanceListChoice(actualPrompt);
if (answer != null)
+ {
+ _logger.LogInformation("Using choice {Choice} for list prompt '{Prompt}'", answer, actualPrompt);
addonSelectString->AtkUnitBase.FireCallbackInt(answer.Value);
+ }
}
private unsafe void CutsceneSelectStringPostSetup(AddonEvent type, AddonArgs args)
int? answer = HandleListChoice(actualPrompt, answers, checkAllSteps);
if (answer != null)
{
+ _logger.LogInformation("Using choice {Choice} for list prompt '{Prompt}'", answer, actualPrompt);
addonSelectIconString->AtkUnitBase.FireCallbackInt(answer.Value);
return;
}
int questSelection = answers.FindIndex(x => GameFunctions.GameStringEquals(questName, x));
if (questSelection >= 0)
{
+ _logger.LogInformation("Selecting quest {QuestName}", questName);
addonSelectIconString->AtkUnitBase.FireCallbackInt(questSelection);
return true;
}
continue;
}
+ _logger.LogInformation("Returning {YesNo} for '{Prompt}'", dialogueChoice.Yes ? "Yes" : "No", actualPrompt);
addonSelectYesno->AtkUnitBase.FireCallbackInt(dialogueChoice.Yes ? 0 : 1);
return true;
}
- if (step is { InteractionType: EInteractionType.SinglePlayerDuty, BossModEnabled: true })
+ if (step is { InteractionType: EInteractionType.SinglePlayerDuty } &&
+ _bossModIpc.IsConfiguredToRunSoloInstance(quest.Id, step.SinglePlayerDutyIndex, step.BossModEnabled))
{
- _logger.LogTrace("DefaultYesNo: probably Single Player Duty");
+ // Most of these are yes/no dialogs "Duty calls, ...".
+ //
+ // For 'Vows of Virtue, Deeds of Cruelty', there's no such dialog, and it just puts you into the instance
+ // after you confirm 'Wait for Krile?'. However, if you fail that duty, you'll get a DifficultySelectYesNo.
+
+ // DifficultySelectYesNo → [0, 2] for very easy
+ _logger.LogInformation("DefaultYesNo: probably Single Player Duty");
addonSelectYesno->AtkUnitBase.FireCallbackInt(0);
return true;
}
(EClassJob.BlackMage, "Magical Ranged Role Quests"),
];
- private ImmutableDictionary<EAetheryteLocation, List<SinglePlayerDutyInfo>> _startingCityBattles = ImmutableDictionary<EAetheryteLocation, List<SinglePlayerDutyInfo>>.Empty;
- private ImmutableDictionary<EExpansionVersion, List<SinglePlayerDutyInfo>> _mainScenarioBattles = ImmutableDictionary<EExpansionVersion, List<SinglePlayerDutyInfo>>.Empty;
- private ImmutableDictionary<EClassJob, List<SinglePlayerDutyInfo>> _jobQuestBattles = ImmutableDictionary<EClassJob, List<SinglePlayerDutyInfo>>.Empty;
- private ImmutableDictionary<EClassJob, List<SinglePlayerDutyInfo>> _roleQuestBattles = ImmutableDictionary<EClassJob, List<SinglePlayerDutyInfo>>.Empty;
+ private ImmutableDictionary<EAetheryteLocation, List<SinglePlayerDutyInfo>> _startingCityBattles =
+ ImmutableDictionary<EAetheryteLocation, List<SinglePlayerDutyInfo>>.Empty;
+
+ private ImmutableDictionary<EExpansionVersion, List<SinglePlayerDutyInfo>> _mainScenarioBattles =
+ ImmutableDictionary<EExpansionVersion, List<SinglePlayerDutyInfo>>.Empty;
+
+ private ImmutableDictionary<EClassJob, List<SinglePlayerDutyInfo>> _jobQuestBattles =
+ ImmutableDictionary<EClassJob, List<SinglePlayerDutyInfo>>.Empty;
+
+ private ImmutableDictionary<EClassJob, List<SinglePlayerDutyInfo>> _roleQuestBattles =
+ ImmutableDictionary<EClassJob, List<SinglePlayerDutyInfo>>.Empty;
+
private ImmutableList<SinglePlayerDutyInfo> _otherRoleQuestBattles = ImmutableList<SinglePlayerDutyInfo>.Empty;
- private ImmutableList<(string Label, List<SinglePlayerDutyInfo>)> _otherQuestBattles = ImmutableList<(string Label, List<SinglePlayerDutyInfo>)>.Empty;
+
+ private ImmutableList<(string Label, List<SinglePlayerDutyInfo>)> _otherQuestBattles =
+ ImmutableList<(string Label, List<SinglePlayerDutyInfo>)>.Empty;
public SinglePlayerDutyConfigComponent(
IDalamudPluginInterface pluginInterface,
{
IQuestInfo questInfo = _questData.GetQuestInfo(questId);
QuestStep questStep = new QuestStep
- {
- SinglePlayerDutyIndex = 0,
- BossModEnabled = false,
- };
+ {
+ SinglePlayerDutyIndex = 0,
+ BossModEnabled = false,
+ };
bool enabled;
if (_questRegistry.TryGetQuest(questId, out var quest))
{
x.Step.SinglePlayerDutyIndex == index);
if (foundStep == default)
{
- _logger.LogWarning("Disabling quest battle for quest {QuestId}, no battle with index {Index} found", questId, index);
+ _logger.LogWarning(
+ "Disabling quest battle for quest {QuestId}, no battle with index {Index} found", questId,
+ index);
enabled = false;
}
else
questInfo.SortKey,
questStep.SinglePlayerDutyIndex,
enabled,
- questStep.BossModEnabled);
+ questStep.BossModEnabled,
+ questStep.BossModNotes);
if (cfcData.ContentFinderConditionId is 332 or 333 or 313 or 334)
startingCityBattles[EAetheryteLocation.Limsa].Add(dutyInfo);
}
}
- if(ImGui.CollapsingHeader("General Role Quests"))
+ if (ImGui.CollapsingHeader("General Role Quests"))
DrawQuestTable("RoleQuestsGeneral", _otherRoleQuestBattles);
}
? SupportedCfcOptions
: UnsupportedCfcOptions;
int value = 0;
- if (Configuration.Duties.WhitelistedDutyCfcIds.Contains(dutyInfo.CfcId))
+ if (Configuration.SinglePlayerDuties.WhitelistedSinglePlayerDutyCfcIds.Contains(dutyInfo.CfcId))
value = 1;
- if (Configuration.Duties.BlacklistedDutyCfcIds.Contains(dutyInfo.CfcId))
+ if (Configuration.SinglePlayerDuties.BlacklistedSinglePlayerDutyCfcIds.Contains(dutyInfo.CfcId))
value = 2;
if (ImGui.TableNextColumn())
ImGuiComponents.HelpMarker("Questionable doesn't include support for this quest.",
FontAwesomeIcon.Times, ImGuiColors.DalamudRed);
}
+ else if (dutyInfo.Notes.Count > 0)
+ {
+ using var color = new ImRaii.Color();
+ color.Push(ImGuiCol.TextDisabled, ImGuiColors.DalamudYellow);
+ ImGui.SameLine();
+ using (ImRaii.PushFont(UiBuilder.IconFont))
+ {
+ ImGui.TextDisabled(FontAwesomeIcon.ExclamationTriangle.ToIconString());
+ }
+
+ if (ImGui.IsItemHovered())
+ {
+ using var _ = ImRaii.Tooltip();
+
+ ImGui.TextColored(ImGuiColors.DalamudYellow, "While testing, the following issues have been found:");
+ foreach (string note in dutyInfo.Notes)
+ ImGui.BulletText(note);
+ }
+ }
}
if (ImGui.TableNextColumn())
ImGui.SetNextItemWidth(200);
if (ImGui.Combo(string.Empty, ref value, labels, labels.Length))
{
- Configuration.Duties.WhitelistedDutyCfcIds.Remove(dutyInfo.CfcId);
- Configuration.Duties.BlacklistedDutyCfcIds.Remove(dutyInfo.CfcId);
+ Configuration.SinglePlayerDuties.WhitelistedSinglePlayerDutyCfcIds.Remove(dutyInfo.CfcId);
+ Configuration.SinglePlayerDuties.BlacklistedSinglePlayerDutyCfcIds.Remove(dutyInfo.CfcId);
if (value == 1)
- Configuration.Duties.WhitelistedDutyCfcIds.Add(dutyInfo.CfcId);
+ Configuration.SinglePlayerDuties.WhitelistedSinglePlayerDutyCfcIds.Add(dutyInfo.CfcId);
else if (value == 2)
- Configuration.Duties.BlacklistedDutyCfcIds.Add(dutyInfo.CfcId);
+ Configuration.SinglePlayerDuties.BlacklistedSinglePlayerDutyCfcIds.Add(dutyInfo.CfcId);
Save();
}
ushort SortKey,
byte Index,
bool Enabled,
- bool BossModEnabledByDefault);
+ bool BossModEnabledByDefault,
+ List<string> Notes);
}