muffin v7.5.13

This commit is contained in:
alydev 2026-08-22 10:25:22 +10:00
parent 911ed68baa
commit acf3e3cb18
69 changed files with 2731 additions and 1425 deletions

View file

@ -31,6 +31,8 @@ internal static class Dive
internal sealed class Task : ITask
{
public bool SmartNavRouted { get; init; }
public override string ToString()
{
return "Dive";
@ -51,6 +53,10 @@ internal static class Dive
{
return false;
}
if (base.Task.SmartNavRouted && !condition[ConditionFlag.Swimming])
{
return false;
}
if (condition[ConditionFlag.Mounted] || condition[ConditionFlag.Swimming])
{
Descend();

View file

@ -80,14 +80,14 @@ internal static class Duty
private EDutyMode GetEffectiveEDutyMode(uint cfcId, EDutyMode? registryDutyMode)
{
if (registryDutyMode.HasValue)
{
return registryDutyMode.Value;
}
if (configuration.Duties.DutyModeOverrides.TryGetValue(cfcId, out var value))
{
return value;
}
if (registryDutyMode.HasValue)
{
return registryDutyMode.Value;
}
EDutyMode defaultDutyMode = configuration.Duties.DefaultDutyMode;
if (defaultDutyMode == EDutyMode.Support && configuration.Duties.AutoUnsyncOverleveled && IsSafelyOverleveled(cfcId))
{
@ -380,7 +380,7 @@ internal static class Duty
}
}
internal sealed record EnableBossModForDutyTask : ITask
internal sealed record EnableBossModForDutyTask(bool ActivateAi = true) : ITask
{
public override string ToString()
{
@ -392,7 +392,7 @@ internal static class Duty
{
protected override bool Start()
{
bossModIpc.EnableAi(BossModIpc.EPreset.Active);
bossModIpc.EnableAi(BossModIpc.EPreset.Active, base.Task.ActivateAi);
IPlayerCharacter localPlayer = objectTable.LocalPlayer;
bool flag;
if (localPlayer != null)
@ -404,18 +404,18 @@ internal static class Duty
if ((uint)(valueOrDefault - 3) <= 1u)
{
flag = true;
goto IL_0077;
goto IL_0082;
}
}
flag = false;
goto IL_0077;
goto IL_0082;
}
goto IL_0087;
IL_0077:
goto IL_0092;
IL_0082:
bool isRanged = flag;
bossModIpc.SetRangeStrategy(BossModIpc.EPreset.Active, isRanged);
goto IL_0087;
IL_0087:
goto IL_0092;
IL_0092:
logger.LogDebug("Enabled BossMod Active preset for AutoDuty run");
return true;
}
@ -463,7 +463,7 @@ internal static class Duty
}
}
internal sealed record EnableBossModPassiveForDutyTask : ITask
internal sealed record EnableBossModPassiveForDutyTask(bool ActivateAi = true) : ITask
{
public override string ToString()
{
@ -475,7 +475,7 @@ internal static class Duty
{
protected override bool Start()
{
bossModIpc.EnableAi(BossModIpc.EPreset.Passive);
bossModIpc.EnableAi(BossModIpc.EPreset.Passive, base.Task.ActivateAi);
logger.LogDebug("Enabled BossMod Passive preset for AutoDuty run (hazard avoidance)");
return true;
}

View file

@ -80,6 +80,8 @@ internal static class EquipRecommended
private bool _checkedOrTriggeredEquipmentUpdate;
private List<uint>? _gameRecommendedItemIds;
private long _timeoutAt;
private List<(int Slot, BestItemRef Item)>? _smartUpgrades;
@ -177,8 +179,7 @@ internal static class EquipRecommended
{
if (!TryStartMove(pendingMove))
{
chatGui.Print($"Equip move {_smartMoveCursor + 1}/{smartMoves.Count} rejected; skipping equip step.", "Questionable", 576);
return ETaskResult.TaskComplete;
throw EquipFailure($"Equip move {_smartMoveCursor + 1}/{smartMoves.Count} was rejected");
}
_currentMoveStarted = true;
_timeoutAt = Environment.TickCount64 + 2000;
@ -196,8 +197,7 @@ internal static class EquipRecommended
}
if (Environment.TickCount64 >= _timeoutAt)
{
chatGui.Print($"Equip move {_smartMoveCursor + 1}/{smartMoves.Count} timed out; skipping equip step.", "Questionable", 576);
return ETaskResult.TaskComplete;
throw EquipFailure($"Equip move {_smartMoveCursor + 1}/{smartMoves.Count} timed out");
}
return ETaskResult.StillRunning;
}
@ -227,11 +227,11 @@ internal static class EquipRecommended
{
return ETaskResult.TaskComplete;
}
if (Environment.TickCount64 < _timeoutAt)
if (Environment.TickCount64 >= _timeoutAt)
{
return ETaskResult.StillRunning;
throw EquipFailure("Recommended gear was not equipped before the timeout");
}
return ETaskResult.TaskComplete;
return ETaskResult.StillRunning;
}
private ETaskResult DirectEquipPhase()
@ -247,20 +247,18 @@ internal static class EquipRecommended
{
return ETaskResult.TaskComplete;
}
if (Environment.TickCount64 < _timeoutAt)
if (Environment.TickCount64 >= _timeoutAt)
{
return ETaskResult.StillRunning;
throw EquipFailure("Recommended gear was not equipped before the timeout");
}
return ETaskResult.TaskComplete;
return ETaskResult.StillRunning;
}
var (num, item) = smartUpgrades[_directEquipCursor];
if (!_directEquipStarted)
{
if (!TryStartDirectEquip(item, num))
{
chatGui.Print($"Direct equip for slot {num} rejected, skipping.", "Questionable", 576);
_directEquipCursor++;
return ETaskResult.StillRunning;
throw EquipFailure($"Direct equip for slot {num} was rejected");
}
_directEquipStarted = true;
_timeoutAt = Environment.TickCount64 + 2000;
@ -274,8 +272,7 @@ internal static class EquipRecommended
}
if (Environment.TickCount64 >= _timeoutAt)
{
_directEquipCursor++;
_directEquipStarted = false;
throw EquipFailure($"Direct equip for slot {num} timed out");
}
return ETaskResult.StillRunning;
}
@ -366,7 +363,8 @@ internal static class EquipRecommended
}
if (!_checkedOrTriggeredEquipmentUpdate)
{
if (IsAllRecommendedGearEquipped())
_gameRecommendedItemIds = SnapshotRecommendedItemIds(ptr);
if (AreAllItemsEquipped(_gameRecommendedItemIds))
{
return ETaskResult.TaskComplete;
}
@ -376,15 +374,15 @@ internal static class EquipRecommended
_checkedOrTriggeredEquipmentUpdate = true;
return ETaskResult.StillRunning;
}
if (IsAllRecommendedGearEquipped())
if (_gameRecommendedItemIds != null && AreAllItemsEquipped(_gameRecommendedItemIds))
{
return ETaskResult.TaskComplete;
}
if (Environment.TickCount64 < _timeoutAt)
if (Environment.TickCount64 >= _timeoutAt)
{
return ETaskResult.StillRunning;
throw EquipFailure("EquipRecommendedGear did not finish before the timeout");
}
return ETaskResult.TaskComplete;
return ETaskResult.StillRunning;
}
private unsafe bool AreUpgradesApplied(IReadOnlyList<(int Slot, BestItemRef Item)> upgrades)
@ -621,19 +619,70 @@ internal static class EquipRecommended
return (byte)classJobLevel;
}
private unsafe bool IsAllRecommendedGearEquipped()
private unsafe static List<uint> SnapshotRecommendedItemIds(RecommendEquipModule* recommendedEquipModule)
{
Span<Pointer<InventoryItem>> recommendedItems = RecommendEquipModule.Instance()->RecommendedItems;
List<uint> list = new List<uint>();
Span<Pointer<InventoryItem>> recommendedItems = recommendedEquipModule->RecommendedItems;
for (int i = 0; i < recommendedItems.Length; i++)
{
Pointer<InventoryItem> pointer = recommendedItems[i];
InventoryItem* value = pointer.Value;
if (value != null && value->ItemId != 0 && !InventoryHelper.IsItemEquipped(value->ItemId))
if (value != null && value->ItemId != 0)
{
return false;
list.Add(((ItemHandle)value->ItemId).Id);
}
}
return true;
return list;
}
private unsafe static bool AreAllItemsEquipped(IReadOnlyList<uint> expectedItemIds)
{
InventoryManager* ptr = InventoryManager.Instance();
if (ptr == null)
{
return false;
}
InventoryContainer* inventoryContainer = ptr->GetInventoryContainer(InventoryType.EquippedItems);
if (inventoryContainer == null)
{
return false;
}
Dictionary<uint, int> dictionary = new Dictionary<uint, int>();
foreach (uint expectedItemId in expectedItemIds)
{
dictionary[expectedItemId] = dictionary.GetValueOrDefault(expectedItemId) + 1;
}
for (int i = 0; i < inventoryContainer->Size; i++)
{
if (dictionary.Count <= 0)
{
break;
}
InventoryItem* inventorySlot = inventoryContainer->GetInventorySlot(i);
if (inventorySlot == null || inventorySlot->ItemId == 0)
{
continue;
}
uint id = ItemHandle.FromInventorySlot(inventorySlot).Id;
if (dictionary.TryGetValue(id, out var value))
{
if (value == 1)
{
dictionary.Remove(id);
}
else
{
dictionary[id] = value - 1;
}
}
}
return dictionary.Count == 0;
}
private TaskException EquipFailure(string message)
{
chatGui.PrintError(message + "; stopping automation.", "Questionable", 576);
return new TaskException(message);
}
public override bool ShouldInterruptOnDamage()

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.ClientState.Objects.Enums;
@ -16,12 +17,13 @@ using Questionable.Controller.Utils;
using Questionable.Functions;
using Questionable.Model;
using Questionable.Model.Questing;
using SmartNav.Data;
namespace Questionable.Controller.Steps.Interactions;
internal static class Interact
{
internal sealed class Factory(Configuration configuration) : ITaskFactory
internal sealed class Factory(Configuration configuration, WarpDataService warpDataService) : ITaskFactory
{
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
{
@ -63,6 +65,25 @@ internal static class Interact
{
yield return new WaitAtEnd.WaitDelay();
}
ushort? targetTerritoryId = step.TargetTerritoryId;
List<uint> list;
if (targetTerritoryId.HasValue)
{
ushort targetTerritoryId2 = targetTerritoryId.GetValueOrDefault();
list = (from x in warpDataService.Warps
where x.NpcDataId == step.DataId && x.SourceTerritoryId == step.TerritoryId && x.DestTerritoryId == targetTerritoryId2
select x.RowId).Distinct().Take(2).ToList();
}
else
{
list = new List<uint>();
}
List<uint> list2 = list;
if (list2.Count == 1)
{
yield return new WarpInteract.Task(step.DataId.Value, list2[0], step.TerritoryId, step.TargetTerritoryId.Value);
yield break;
}
uint value = step.DataId.Value;
EInteractionType interactionType2 = step.InteractionType;
int skipMarkerCheck;
@ -74,20 +95,17 @@ internal static class Interact
SkipStepConditions stepIf = skipConditions.StepIf;
if (stepIf != null && stepIf.Never)
{
goto IL_024a;
goto IL_03d7;
}
}
if (step.InteractionType != EInteractionType.PurchaseItem)
{
skipMarkerCheck = ((step.DataId == 1052475) ? 1 : 0);
goto IL_024b;
goto IL_03d8;
}
}
goto IL_024a;
IL_024a:
skipMarkerCheck = 1;
goto IL_024b;
IL_024b:
goto IL_03d7;
IL_03d8:
uint? pickUpItemId = step.PickUpItemId ?? step.GCPurchase?.ItemId;
byte? taxiStandId = step.TaxiStandId;
SkipStepConditions? skipConditions2 = step.SkipConditions?.StepIf;
@ -95,6 +113,10 @@ internal static class Interact
uint? purchaseItemId = ((step.InteractionType == EInteractionType.PurchaseItem) ? step.ItemId : ((uint?)null));
int purchaseItemCount = ((step.InteractionType == EInteractionType.PurchaseItem) ? step.ItemCount.GetValueOrDefault() : 0);
yield return new Task(value, quest, interactionType2, (byte)skipMarkerCheck != 0, pickUpItemId, taxiStandId, skipConditions2, completionQuestVariablesFlags, null, purchaseItemId, purchaseItemCount);
yield break;
IL_03d7:
skipMarkerCheck = 1;
goto IL_03d8;
}
}

View file

@ -33,7 +33,7 @@ internal static class SinglePlayerDuty
public const ushort Naadam = 688;
}
internal sealed class Factory(BossModIpc bossModIpc, WrathComboModule wrathComboModule, RotationSolverRebornModule rsrModule, Configuration configuration, TerritoryData territoryData, QuestFunctions questFunctions, DutyRetryState dutyRetryState, ICondition condition, IClientState clientState, IObjectTable objectTable) : ITaskFactory
internal sealed class Factory(BossModIpc bossModIpc, WrathComboModule wrathComboModule, RotationSolverRebornModule rsrModule, Configuration configuration, TerritoryData territoryData, QuestFunctions questFunctions, GameFunctions gameFunctions, DutyRetryState dutyRetryState, ICondition condition, IClientState clientState, IObjectTable objectTable) : ITaskFactory
{
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
{
@ -54,7 +54,12 @@ internal static class SinglePlayerDuty
byte seqBefore = questProgressInfo?.Sequence ?? 0;
IReadOnlyList<byte> varsBefore = questProgressInfo?.Variables.ToArray();
dutyRetryState.Reset();
List<ITask> dutyTasks = new List<ITask>();
List<ITask> dutyTasks = new List<ITask>
{
new StartSinglePlayerDuty(contentFinderConditionData.ContentFinderConditionId),
new WaitAtStart.WaitDelay(TimeSpan.FromSeconds(10L)),
new WaitCondition.Task(() => !gameFunctions.IsOccupied(), "Wait(solo duty ready)")
};
if (wrathComboModule.IsAvailable())
{
dutyTasks.Add(new Duty.EnableWrathForDutyTask());
@ -65,14 +70,12 @@ internal static class SinglePlayerDuty
}
if (configuration.General.CombatModule == Configuration.ECombatModule.BossMod && bossModIpc.IsSupported())
{
dutyTasks.Add(new Duty.EnableBossModForDutyTask());
dutyTasks.Add(new Duty.EnableBossModForDutyTask(configuration.SinglePlayerDuties.EnableBossModAi));
}
else if (bossModIpc.IsSupported())
{
dutyTasks.Add(new Duty.EnableBossModPassiveForDutyTask());
dutyTasks.Add(new Duty.EnableBossModPassiveForDutyTask(configuration.SinglePlayerDuties.EnableBossModAi));
}
dutyTasks.Add(new StartSinglePlayerDuty(contentFinderConditionData.ContentFinderConditionId));
dutyTasks.Add(new WaitAtStart.WaitDelay(TimeSpan.FromSeconds(2L)));
dutyTasks.Add(new EnableAi());
if (contentFinderConditionData.TerritoryId == 1052)
{
@ -132,8 +135,6 @@ internal static class SinglePlayerDuty
internal sealed class StartSinglePlayerDutyExecutor(ICondition condition) : TaskExecutor<StartSinglePlayerDuty>()
{
private long _enteredAtMs;
protected override bool Start()
{
return true;
@ -149,14 +150,6 @@ internal static class SinglePlayerDuty
{
return ETaskResult.StillRunning;
}
if (_enteredAtMs == 0L)
{
_enteredAtMs = Environment.TickCount64;
}
if (Environment.TickCount64 - _enteredAtMs < 2000)
{
return ETaskResult.StillRunning;
}
return ETaskResult.TaskComplete;
}