--- /dev/null
+using System;
+using System.Numerics;
+using Dalamud.Plugin.Services;
+using FFXIVClientStructs.FFXIV.Client.Game;
+using Microsoft.Extensions.Logging;
+using Questionable.Model.Questing;
+
+namespace Questionable.Controller.Steps.Shared;
+
+internal sealed class ExtraConditionUtils
+{
+ private readonly Configuration _configuration;
+ private readonly IClientState _clientState;
+ private readonly ILogger<ExtraConditionUtils> _logger;
+
+ public ExtraConditionUtils(
+ Configuration configuration,
+ IClientState clientState,
+ ILogger<ExtraConditionUtils> logger)
+ {
+ _configuration = configuration;
+ _clientState = clientState;
+ _logger = logger;
+ }
+
+ public bool MatchesExtraCondition(EExtraSkipCondition skipCondition)
+ {
+ var position = _clientState.LocalPlayer?.Position;
+ return position != null &&
+ _clientState.TerritoryType != 0 &&
+ MatchesExtraCondition(skipCondition, position.Value, _clientState.TerritoryType);
+ }
+
+ public bool MatchesExtraCondition(EExtraSkipCondition skipCondition, Vector3 position, ushort territoryType)
+ {
+ return skipCondition switch
+ {
+ EExtraSkipCondition.WakingSandsMainArea => territoryType == 212 && position.X < 24,
+ EExtraSkipCondition.WakingSandsSolar => territoryType == 212 && position.X >= 24,
+ EExtraSkipCondition.RisingStonesSolar => territoryType == 351 && position.Z <= -28,
+ EExtraSkipCondition.RoguesGuild => territoryType == 129 && position.Y <= -115,
+ EExtraSkipCondition.NotRoguesGuild => territoryType == 129 && position.Y > -115,
+ EExtraSkipCondition.DockStorehouse => territoryType == 137 && position.Y <= -20,
+ EExtraSkipCondition.SkipFreeFantasia => ShouldSkipFreeFantasia(),
+ _ => throw new ArgumentOutOfRangeException(nameof(skipCondition), skipCondition, null)
+ };
+ }
+
+ private unsafe bool ShouldSkipFreeFantasia()
+ {
+ if (!_configuration.General.PickUpFreeFantasia)
+ {
+ _logger.LogInformation("Skipping fantasia step, as free fantasia is disabled in the configuration");
+ return true;
+ }
+
+ bool foundFestival = false;
+ for (int i = 0; i < GameMain.Instance()->ActiveFestivals.Length; ++i)
+ {
+ if (GameMain.Instance()->ActiveFestivals[i].Id == 160)
+ {
+ foundFestival = true;
+ break;
+ }
+ }
+
+ if (!foundFestival)
+ {
+ _logger.LogInformation("Skipping fantasia step, as free fantasia moogle is not available");
+ return true;
+ }
+
+ return false;
+ }
+}
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Dalamud.Game.ClientState.Conditions;
GameFunctions gameFunctions,
QuestFunctions questFunctions,
IClientState clientState,
- ICondition condition) : TaskExecutor<SkipTask>
+ ICondition condition,
+ ExtraConditionUtils extraConditionUtils) : TaskExecutor<SkipTask>
{
- protected override unsafe bool Start()
+ protected override bool Start()
{
var skipConditions = Task.SkipConditions;
var step = Task.Step;
logger.LogInformation("Checking skip conditions; {ConfiguredConditions}", string.Join(",", skipConditions));
+ if (CheckFlyingCondition(step, skipConditions))
+ return true;
+
+ if (CheckUnlockedMountCondition(skipConditions))
+ return true;
+
+ if (CheckDivingCondition(skipConditions))
+ return true;
+
+ if (CheckTerritoryCondition(skipConditions))
+ return true;
+
+ if (CheckQuestConditions(skipConditions))
+ return true;
+
+ if (CheckTargetableCondition(step, skipConditions))
+ return true;
+
+ if (CheckNameplateCondition(step, skipConditions))
+ return true;
+
+ if (CheckItemCondition(step, skipConditions))
+ return true;
+
+ if (CheckAetheryteCondition(step, skipConditions))
+ return true;
+
+ if (CheckAethernetCondition(step))
+ return true;
+
+ if (CheckQuestWorkConditions(elementId, step))
+ return true;
+
+ if (CheckJobCondition(step))
+ return true;
+
+ if (CheckPositionCondition(skipConditions))
+ return true;
+
+ if (skipConditions.ExtraCondition != null && skipConditions.ExtraCondition != EExtraSkipCondition.None &&
+ extraConditionUtils.MatchesExtraCondition(skipConditions.ExtraCondition.Value))
+ {
+ logger.LogInformation("Skipping step, extra condition {} matches", skipConditions.ExtraCondition);
+ return true;
+ }
+
+ if (CheckPickUpTurnInQuestIds(step))
+ return true;
+
+ return false;
+ }
+
+ private bool CheckFlyingCondition(QuestStep step, SkipStepConditions skipConditions)
+ {
if (skipConditions.Flying == ELockedSkipCondition.Unlocked &&
gameFunctions.IsFlyingUnlocked(step.TerritoryId))
{
return true;
}
+ return false;
+ }
+
+ private unsafe bool CheckUnlockedMountCondition(SkipStepConditions skipConditions)
+ {
if (skipConditions.Chocobo == ELockedSkipCondition.Unlocked &&
PlayerState.Instance()->IsMountUnlocked(1))
{
return true;
}
- if (skipConditions.Diving == true && condition[ConditionFlag.Diving])
+ return false;
+ }
+
+ private bool CheckTerritoryCondition(SkipStepConditions skipConditions)
+ {
+ if (skipConditions.InTerritory.Count > 0 &&
+ skipConditions.InTerritory.Contains(clientState.TerritoryType))
{
- logger.LogInformation("Skipping step, as you're currently diving underwater");
+ logger.LogInformation("Skipping step, as in a skip.InTerritory");
return true;
}
- if (skipConditions.Diving == false && !condition[ConditionFlag.Diving])
+ if (skipConditions.NotInTerritory.Count > 0 &&
+ !skipConditions.NotInTerritory.Contains(clientState.TerritoryType))
{
- logger.LogInformation("Skipping step, as you're not currently diving underwater");
+ logger.LogInformation("Skipping step, as not in a skip.NotInTerritory");
return true;
}
- if (skipConditions.InTerritory.Count > 0 &&
- skipConditions.InTerritory.Contains(clientState.TerritoryType))
+ return false;
+ }
+
+ private bool CheckDivingCondition(SkipStepConditions skipConditions)
+ {
+ if (skipConditions.Diving == true && condition[ConditionFlag.Diving])
{
- logger.LogInformation("Skipping step, as in a skip.InTerritory");
+ logger.LogInformation("Skipping step, as you're currently diving underwater");
return true;
}
- if (skipConditions.NotInTerritory.Count > 0 &&
- !skipConditions.NotInTerritory.Contains(clientState.TerritoryType))
+ if (skipConditions.Diving == false && !condition[ConditionFlag.Diving])
{
- logger.LogInformation("Skipping step, as not in a skip.NotInTerritory");
+ logger.LogInformation("Skipping step, as you're not currently diving underwater");
return true;
}
+ return false;
+ }
+
+ private bool CheckQuestConditions(SkipStepConditions skipConditions)
+ {
if (skipConditions.QuestsCompleted.Count > 0 &&
skipConditions.QuestsCompleted.All(questFunctions.IsQuestComplete))
{
return true;
}
+ return false;
+ }
+
+ private bool CheckTargetableCondition(QuestStep step, SkipStepConditions skipConditions)
+ {
if (skipConditions.NotTargetable &&
step is { DataId: not null })
{
}
}
+ return false;
+ }
+
+ private unsafe bool CheckNameplateCondition(QuestStep step, SkipStepConditions skipConditions)
+ {
if (skipConditions.NotNamePlateIconId.Count > 0 &&
step is { DataId: not null })
{
}
}
+ return false;
+ }
+
+ private unsafe bool CheckItemCondition(QuestStep step, SkipStepConditions skipConditions)
+ {
if (skipConditions.Item is { NotInInventory: true } && step is { ItemId: not null })
{
InventoryManager* inventoryManager = InventoryManager.Instance();
}
}
+ return false;
+ }
+
+ private bool CheckAetheryteCondition(QuestStep step, SkipStepConditions skipConditions)
+ {
if (step is
{
DataId: not null,
return true;
}
+ return false;
+ }
+
+ private bool CheckAethernetCondition(QuestStep step)
+ {
if (step is { DataId: not null, InteractionType: EInteractionType.AttuneAetherCurrent } &&
gameFunctions.IsAetherCurrentUnlocked(step.DataId.Value))
{
return true;
}
+ return false;
+ }
+
+ private bool CheckQuestWorkConditions(ElementId elementId, QuestStep step)
+ {
QuestProgressInfo? questWork = questFunctions.GetQuestProgressInfo(elementId);
if (questWork != null)
{
}
}
+ return false;
+ }
+
+ private bool CheckJobCondition(QuestStep step)
+ {
if (step is { RequiredCurrentJob.Count: > 0 })
{
List<EClassJob> expectedJobs =
}
}
+ return false;
+ }
+
+ private bool CheckPositionCondition(SkipStepConditions skipConditions)
+ {
if (skipConditions.NearPosition is { } nearPosition &&
clientState.TerritoryType == nearPosition.TerritoryId)
{
}
}
- if (skipConditions.ExtraCondition != null && skipConditions.ExtraCondition != EExtraSkipCondition.None)
- {
- var position = clientState.LocalPlayer?.Position;
- if (position != null &&
- clientState.TerritoryType != 0 &&
- MatchesExtraCondition(skipConditions.ExtraCondition.Value, position.Value,
- clientState.TerritoryType))
- {
- logger.LogInformation("Skipping step, extra condition {} matches", skipConditions.ExtraCondition);
- return true;
- }
- }
+ return false;
+ }
+ private bool CheckPickUpTurnInQuestIds(QuestStep step)
+ {
if (step.PickUpQuestId != null && questFunctions.IsQuestAcceptedOrComplete(step.PickUpQuestId))
{
logger.LogInformation("Skipping step, as we have already picked up the relevant quest");
return false;
}
- private static bool MatchesExtraCondition(EExtraSkipCondition condition, Vector3 position, ushort territoryType)
- {
- return condition switch
- {
- EExtraSkipCondition.WakingSandsMainArea => territoryType == 212 && position.X < 24,
- EExtraSkipCondition.WakingSandsSolar => territoryType == 212 && position.X >= 24,
- EExtraSkipCondition.RisingStonesSolar => territoryType == 351 && position.Z <= -28,
- EExtraSkipCondition.RoguesGuild => territoryType == 129 && position.Y <= -115,
- EExtraSkipCondition.NotRoguesGuild => territoryType == 129 && position.Y > -115,
- EExtraSkipCondition.DockStorehouse => territoryType == 137 && position.Y <= -20,
- _ => throw new ArgumentOutOfRangeException(nameof(condition), condition, null)
- };
- }
-
public override ETaskResult Update() => ETaskResult.SkipRemainingTasksForStep;
public override bool ShouldInterruptOnDamage() => false;