muffin v7.38.8

This commit is contained in:
alydev 2025-11-30 10:36:46 +10:00
parent 5e2d8f648b
commit 3e10cbbbf2
51 changed files with 2585 additions and 1972 deletions

View file

@ -4,6 +4,7 @@ using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices;
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Plugin.Services;
using Microsoft.Extensions.Logging;
using Questionable.Controller.Steps.Common;
@ -50,7 +51,7 @@ internal static class AethernetShortcut
}
}
internal sealed class UseAethernetShortcut(ILogger<UseAethernetShortcut> logger, AetheryteFunctions aetheryteFunctions, GameFunctions gameFunctions, QuestFunctions questFunctions, IClientState clientState, AetheryteData aetheryteData, TerritoryData territoryData, LifestreamIpc lifestreamIpc, MovementController movementController, ICondition condition) : TaskExecutor<Task>()
internal sealed class UseAethernetShortcut(ILogger<UseAethernetShortcut> logger, AetheryteFunctions aetheryteFunctions, GameFunctions gameFunctions, QuestFunctions questFunctions, IClientState clientState, IObjectTable objectTable, AetheryteData aetheryteData, TerritoryData territoryData, LifestreamIpc lifestreamIpc, MovementController movementController, ICondition condition) : TaskExecutor<Task>()
{
private bool _moving;
@ -98,7 +99,12 @@ internal static class AethernetShortcut
if (aetheryteFunctions.IsAetheryteUnlocked(base.Task.From) && aetheryteFunctions.IsAetheryteUnlocked(base.Task.To))
{
ushort territoryType = clientState.TerritoryType;
Vector3 playerPosition = clientState.LocalPlayer.Position;
IGameObject gameObject = objectTable[0];
if (gameObject == null)
{
return false;
}
Vector3 playerPosition = gameObject.Position;
if (aetheryteData.CalculateDistance(playerPosition, territoryType, base.Task.From) < aetheryteData.CalculateDistance(playerPosition, territoryType, base.Task.To))
{
if (aetheryteData.CalculateDistance(playerPosition, territoryType, base.Task.From) < (base.Task.From.IsFirmamentAetheryte() ? 11f : 4f))
@ -202,7 +208,7 @@ internal static class AethernetShortcut
DoTeleport();
return ETaskResult.StillRunning;
}
Vector3? vector = clientState.LocalPlayer?.Position;
Vector3? vector = objectTable[0]?.Position;
if (!vector.HasValue)
{
return ETaskResult.StillRunning;

View file

@ -4,6 +4,7 @@ using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices;
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Plugin.Services;
using Microsoft.Extensions.Logging;
using Questionable.Controller.Steps.Common;
@ -45,7 +46,7 @@ internal static class AetheryteShortcut
}
}
internal sealed class UseAetheryteShortcut(ILogger<UseAetheryteShortcut> logger, AetheryteFunctions aetheryteFunctions, QuestFunctions questFunctions, IClientState clientState, IChatGui chatGui, ICondition condition, AetheryteData aetheryteData, ExtraConditionUtils extraConditionUtils) : TaskExecutor<Task>()
internal sealed class UseAetheryteShortcut(ILogger<UseAetheryteShortcut> logger, AetheryteFunctions aetheryteFunctions, QuestFunctions questFunctions, IClientState clientState, IObjectTable objectTable, IChatGui chatGui, ICondition condition, AetheryteData aetheryteData, ExtraConditionUtils extraConditionUtils) : TaskExecutor<Task>()
{
private bool _teleported;
@ -116,14 +117,15 @@ internal static class AetheryteShortcut
return true;
}
}
IGameObject gameObject = objectTable[0];
NearPositionCondition nearPosition = skipAetheryteCondition.NearPosition;
if (nearPosition != null && clientState.TerritoryType == nearPosition.TerritoryId && Vector3.Distance(nearPosition.Position, clientState.LocalPlayer.Position) <= nearPosition.MaximumDistance)
if (nearPosition != null && clientState.TerritoryType == nearPosition.TerritoryId && gameObject != null && Vector3.Distance(nearPosition.Position, gameObject.Position) <= nearPosition.MaximumDistance)
{
logger.LogInformation("Skipping aetheryte shortcut, as we're near the position");
return true;
}
NearPositionCondition notNearPosition = skipAetheryteCondition.NotNearPosition;
if (notNearPosition != null && clientState.TerritoryType == notNearPosition.TerritoryId && notNearPosition.MaximumDistance <= Vector3.Distance(notNearPosition.Position, clientState.LocalPlayer.Position))
if (notNearPosition != null && clientState.TerritoryType == notNearPosition.TerritoryId && gameObject != null && notNearPosition.MaximumDistance <= Vector3.Distance(notNearPosition.Position, gameObject.Position))
{
logger.LogInformation("Skipping aetheryte shortcut, as we're not near the position");
return true;
@ -134,23 +136,27 @@ internal static class AetheryteShortcut
return true;
}
}
if (base.Task.ExpectedTerritoryId == territoryType && !skipAetheryteCondition.Never)
if (base.Task.ExpectedTerritoryId == territoryType)
{
if (skipAetheryteCondition != null && skipAetheryteCondition.InSameTerritory)
IGameObject gameObject2 = objectTable[0];
if (gameObject2 != null && !skipAetheryteCondition.Never)
{
logger.LogInformation("Skipping aetheryte teleport due to SkipCondition (InSameTerritory)");
return true;
}
Vector3 position = clientState.LocalPlayer.Position;
if (base.Task.Step.Position.HasValue && (position - base.Task.Step.Position.Value).Length() < base.Task.Step.CalculateActualStopDistance())
{
logger.LogInformation("Skipping aetheryte teleport, we're near the target");
return true;
}
if (aetheryteData.CalculateDistance(position, territoryType, base.Task.TargetAetheryte) < 20f || (base.Task.Step.AethernetShortcut != null && (aetheryteData.CalculateDistance(position, territoryType, base.Task.Step.AethernetShortcut.From) < 20f || aetheryteData.CalculateDistance(position, territoryType, base.Task.Step.AethernetShortcut.To) < 20f)))
{
logger.LogInformation("Skipping aetheryte teleport");
return true;
if (skipAetheryteCondition != null && skipAetheryteCondition.InSameTerritory)
{
logger.LogInformation("Skipping aetheryte teleport due to SkipCondition (InSameTerritory)");
return true;
}
Vector3 position = gameObject2.Position;
if (base.Task.Step.Position.HasValue && (position - base.Task.Step.Position.Value).Length() < base.Task.Step.CalculateActualStopDistance())
{
logger.LogInformation("Skipping aetheryte teleport, we're near the target");
return true;
}
if (aetheryteData.CalculateDistance(position, territoryType, base.Task.TargetAetheryte) < 20f || (base.Task.Step.AethernetShortcut != null && (aetheryteData.CalculateDistance(position, territoryType, base.Task.Step.AethernetShortcut.From) < 20f || aetheryteData.CalculateDistance(position, territoryType, base.Task.Step.AethernetShortcut.To) < 20f)))
{
logger.LogInformation("Skipping aetheryte teleport");
return true;
}
}
}
}
@ -208,7 +214,7 @@ internal static class AetheryteShortcut
}
}
internal sealed class MoveAwayFromAetheryteExecutor(MoveExecutor moveExecutor, AetheryteData aetheryteData, IClientState clientState) : TaskExecutor<MoveAwayFromAetheryte>()
internal sealed class MoveAwayFromAetheryteExecutor(MoveExecutor moveExecutor, AetheryteData aetheryteData, IClientState clientState, IObjectTable objectTable) : TaskExecutor<MoveAwayFromAetheryte>()
{
private static readonly Dictionary<EAetheryteLocation, List<Vector3>> AetherytesToMoveFrom;
@ -219,7 +225,12 @@ internal static class AetheryteShortcut
protected override bool Start()
{
Vector3 playerPosition = clientState.LocalPlayer.Position;
IGameObject gameObject = objectTable[0];
if (gameObject == null)
{
return false;
}
Vector3 playerPosition = gameObject.Position;
if (aetheryteData.CalculateDistance(playerPosition, clientState.TerritoryType, base.Task.TargetAetheryte) >= 20f)
{
return false;

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
@ -43,7 +44,7 @@ internal static class Craft
}
}
internal sealed class DoCraft(IDataManager dataManager, IClientState clientState, ArtisanIpc artisanIpc, ILogger<DoCraft> logger) : TaskExecutor<CraftTask>()
internal sealed class DoCraft(IDataManager dataManager, IObjectTable objectTable, ArtisanIpc artisanIpc, ILogger<DoCraft> logger) : TaskExecutor<CraftTask>()
{
protected override bool Start()
{
@ -57,7 +58,7 @@ internal static class Craft
{
throw new TaskException($"Item {base.Task.ItemId} is not craftable");
}
uint num = (EClassJob)clientState.LocalPlayer.ClassJob.RowId switch
uint num = (EClassJob?)(objectTable[0] as ICharacter)?.ClassJob.RowId switch
{
EClassJob.Carpenter => rowOrDefault.Value.CRP.RowId,
EClassJob.Blacksmith => rowOrDefault.Value.BSM.RowId,

View file

@ -9,14 +9,17 @@ internal sealed class ExtraConditionUtils
{
private readonly IClientState _clientState;
public ExtraConditionUtils(IClientState clientState)
private readonly IObjectTable _objectTable;
public ExtraConditionUtils(IClientState clientState, IObjectTable objectTable)
{
_clientState = clientState;
_objectTable = objectTable;
}
public bool MatchesExtraCondition(EExtraSkipCondition skipCondition)
{
Vector3? vector = _clientState.LocalPlayer?.Position;
Vector3? vector = _objectTable[0]?.Position;
if (vector.HasValue && _clientState.TerritoryType != 0)
{
return MatchesExtraCondition(skipCondition, vector.Value, _clientState.TerritoryType);

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Game.Text;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Plugin.Services;
@ -42,7 +43,7 @@ internal static class Gather
}
}
internal sealed class DelayedGatheringExecutor(GatheringPointRegistry gatheringPointRegistry, TerritoryData territoryData, IClientState clientState, IServiceProvider serviceProvider, ILogger<DelayedGatheringExecutor> logger) : TaskExecutor<DelayedGatheringTask>(), IExtraTaskCreator, ITaskExecutor
internal sealed class DelayedGatheringExecutor(GatheringPointRegistry gatheringPointRegistry, TerritoryData territoryData, IClientState clientState, IObjectTable objectTable, IServiceProvider serviceProvider, ILogger<DelayedGatheringExecutor> logger) : TaskExecutor<DelayedGatheringTask>(), IExtraTaskCreator, ITaskExecutor
{
protected override bool Start()
{
@ -56,8 +57,8 @@ internal static class Gather
public IEnumerable<ITask> CreateExtraTasks()
{
EClassJob rowId = (EClassJob)clientState.LocalPlayer.ClassJob.RowId;
if (!gatheringPointRegistry.TryGetGatheringPointId(base.Task.GatheredItem.ItemId, rowId, out GatheringPointId gatheringPointId))
EClassJob valueOrDefault = ((EClassJob?)(objectTable[0] as ICharacter)?.ClassJob.RowId).GetValueOrDefault();
if (!gatheringPointRegistry.TryGetGatheringPointId(base.Task.GatheredItem.ItemId, valueOrDefault, out GatheringPointId gatheringPointId))
{
throw new TaskException($"No gathering point found for item {base.Task.GatheredItem.ItemId}");
}
@ -69,7 +70,7 @@ internal static class Gather
{
yield break;
}
switch (rowId)
switch (valueOrDefault)
{
case EClassJob.Miner:
yield return new Questionable.Controller.Steps.Interactions.Action.TriggerStatusIfMissing(EStatus.Prospect, EAction.Prospect);

View file

@ -45,7 +45,7 @@ internal static class SkipCondition
}
}
internal sealed class CheckSkip(ILogger<CheckSkip> logger, Configuration configuration, AetheryteFunctions aetheryteFunctions, GameFunctions gameFunctions, QuestFunctions questFunctions, IClientState clientState, ICondition condition, ExtraConditionUtils extraConditionUtils, ClassJobUtils classJobUtils) : TaskExecutor<SkipTask>()
internal sealed class CheckSkip(ILogger<CheckSkip> logger, Configuration configuration, AetheryteFunctions aetheryteFunctions, GameFunctions gameFunctions, QuestFunctions questFunctions, IClientState clientState, IObjectTable objectTable, ICondition condition, ExtraConditionUtils extraConditionUtils, ClassJobUtils classJobUtils) : TaskExecutor<SkipTask>()
{
protected override bool Start()
{
@ -200,9 +200,10 @@ internal static class SkipCondition
if (skipConditions.NotTargetable && step != null && step.DataId.HasValue)
{
IGameObject gameObject = gameFunctions.FindObjectByDataId(step.DataId.Value);
IGameObject gameObject2 = objectTable[0];
if (gameObject == null)
{
if ((step.Position.GetValueOrDefault() - clientState.LocalPlayer.Position).Length() < 100f)
if (gameObject2 != null && (step.Position.GetValueOrDefault() - gameObject2.Position).Length() < 100f)
{
logger.LogInformation("Skipping step, object is not nearby (but we are)");
return true;
@ -340,9 +341,10 @@ internal static class SkipCondition
private bool CheckLevelCondition(SkipStepConditions skipConditions)
{
if (skipConditions.MinimumLevel.HasValue && clientState.LocalPlayer != null && clientState.LocalPlayer.Level >= skipConditions.MinimumLevel.Value)
ICharacter character = objectTable[0] as ICharacter;
if (skipConditions.MinimumLevel.HasValue && character != null && character.Level >= skipConditions.MinimumLevel.Value)
{
logger.LogInformation("Skipping step, as player level {CurrentLevel} >= minimum level {MinLevel}", clientState.LocalPlayer.Level, skipConditions.MinimumLevel.Value);
logger.LogInformation("Skipping step, as player level {CurrentLevel} >= minimum level {MinLevel}", character.Level, skipConditions.MinimumLevel.Value);
return true;
}
return false;
@ -407,9 +409,9 @@ internal static class SkipCondition
if (requiredCurrentJob != null && requiredCurrentJob.Count > 0)
{
List<EClassJob> list = step.RequiredCurrentJob.SelectMany((EExtendedClassJob x) => classJobUtils.AsIndividualJobs(x, elementId)).ToList();
EClassJob rowId = (EClassJob)clientState.LocalPlayer.ClassJob.RowId;
logger.LogInformation("Checking current job {CurrentJob} against {ExpectedJobs}", rowId, string.Join(",", list));
if (!list.Contains(rowId))
EClassJob valueOrDefault = ((EClassJob?)(objectTable[0] as ICharacter)?.ClassJob.RowId).GetValueOrDefault();
logger.LogInformation("Checking current job {CurrentJob} against {ExpectedJobs}", valueOrDefault, string.Join(",", list));
if (!list.Contains(valueOrDefault))
{
logger.LogInformation("Skipping step, as step requires a different job");
return true;
@ -421,14 +423,15 @@ internal static class SkipCondition
private bool CheckPositionCondition(SkipStepConditions skipConditions)
{
IGameObject gameObject = objectTable[0];
NearPositionCondition nearPosition = skipConditions.NearPosition;
if (nearPosition != null && clientState.TerritoryType == nearPosition.TerritoryId && Vector3.Distance(nearPosition.Position, clientState.LocalPlayer.Position) <= nearPosition.MaximumDistance)
if (nearPosition != null && clientState.TerritoryType == nearPosition.TerritoryId && gameObject != null && Vector3.Distance(nearPosition.Position, gameObject.Position) <= nearPosition.MaximumDistance)
{
logger.LogInformation("Skipping step, as we're near the position");
return true;
}
NearPositionCondition notNearPosition = skipConditions.NotNearPosition;
if (notNearPosition != null && clientState.TerritoryType == notNearPosition.TerritoryId && notNearPosition.MaximumDistance <= Vector3.Distance(notNearPosition.Position, clientState.LocalPlayer.Position))
if (notNearPosition != null && clientState.TerritoryType == notNearPosition.TerritoryId && gameObject != null && notNearPosition.MaximumDistance <= Vector3.Distance(notNearPosition.Position, gameObject.Position))
{
logger.LogInformation("Skipping step, as we're not near the position");
return true;
@ -479,7 +482,7 @@ internal static class SkipCondition
private unsafe bool IsBetterOrEqualItemEquipped(uint itemId)
{
if (clientState.LocalPlayer == null)
if (objectTable[0] == null)
{
return false;
}

View file

@ -1,4 +1,5 @@
using System.Linq;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.UI.Misc;
using LLib.GameData;
@ -31,11 +32,11 @@ internal static class SwitchClassJob
}
}
internal sealed class SwitchClassJobExecutor(IClientState clientState) : AbstractDelayedTaskExecutor<Task>()
internal sealed class SwitchClassJobExecutor(IObjectTable objectTable) : AbstractDelayedTaskExecutor<Task>()
{
protected unsafe override bool StartInternal()
{
if (clientState.LocalPlayer.ClassJob.RowId == (uint)base.Task.ClassJob)
if ((objectTable[0] as ICharacter)?.ClassJob.RowId == (uint?)base.Task.ClassJob)
{
return false;
}

View file

@ -17,7 +17,7 @@ namespace Questionable.Controller.Steps.Shared;
internal static class WaitAtEnd
{
internal sealed class Factory(IClientState clientState, ICondition condition, TerritoryData territoryData, AutoDutyIpc autoDutyIpc, BossModIpc bossModIpc) : ITaskFactory
internal sealed class Factory(IClientState clientState, IObjectTable objectTable, ICondition condition, TerritoryData territoryData, AutoDutyIpc autoDutyIpc, BossModIpc bossModIpc) : ITaskFactory
{
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
{
@ -129,10 +129,10 @@ internal static class WaitAtEnd
}
else
{
Vector3 lastPosition = step.Position ?? clientState.LocalPlayer?.Position ?? Vector3.Zero;
Vector3 lastPosition = step.Position ?? objectTable[0]?.Position ?? Vector3.Zero;
task = new WaitCondition.Task(delegate
{
Vector3? vector = clientState.LocalPlayer?.Position;
Vector3? vector = objectTable[0]?.Position;
return vector.HasValue && (lastPosition - vector.Value).Length() > 2f;
}, "Wait(tp away from " + lastPosition.ToString("G", CultureInfo.InvariantCulture) + ")");
}