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

@ -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()