muffin v6.12

This commit is contained in:
alydev 2025-10-09 07:53:51 +10:00
parent cfb4dea47e
commit c8197297b2
58 changed files with 40038 additions and 58059 deletions

View file

@ -5,6 +5,7 @@ using System.Linq;
using System.Numerics;
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.ClientState.Keys;
using Dalamud.Game.ClientState.Objects.SubKinds;
using Dalamud.Game.Gui.Toast;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Plugin.Services;
@ -289,11 +290,11 @@ internal sealed class QuestController : MiniTaskController<QuestController>
_safeAnimationEnd = DateTime.Now.AddSeconds(1f + num);
}
}
UpdateCurrentQuest();
if (AutomationType == EAutomationType.Manual && !IsRunning && !IsQuestWindowOpen)
{
return;
}
UpdateCurrentQuest();
if (!_clientState.IsLoggedIn)
{
StopAllDueToConditionFailed("Logged out");
@ -320,6 +321,17 @@ internal sealed class QuestController : MiniTaskController<QuestController>
return;
}
}
if (_configuration.Stop.Enabled && _configuration.Stop.SequenceToStopAfter && CurrentQuest != null)
{
int sequence = CurrentQuest.Sequence;
if (sequence >= _configuration.Stop.TargetSequence && IsRunning)
{
_logger.LogInformation("Reached quest sequence stop condition (sequence: {CurrentSequence}, target: {TargetSequence})", sequence, _configuration.Stop.TargetSequence);
_chatGui.Print($"Quest sequence {sequence} reached target sequence {_configuration.Stop.TargetSequence}.", "Questionable", 576);
Stop($"Sequence stop condition reached [{sequence}]");
return;
}
}
bool flag = AutomationType == EAutomationType.Automatic && (_taskQueue.AllTasksComplete || _taskQueue.CurrentTaskExecutor?.CurrentTask is WaitAtEnd.WaitQuestAccepted);
bool flag2;
if (flag)
@ -331,14 +343,14 @@ internal sealed class QuestController : MiniTaskController<QuestController>
if (step == 0 || step == 255)
{
flag2 = true;
goto IL_02de;
goto IL_0422;
}
}
flag2 = false;
goto IL_02de;
goto IL_0422;
}
goto IL_02e2;
IL_02e2:
goto IL_0426;
IL_0426:
if (flag && DateTime.Now >= CurrentQuest.StepProgress.StartedAt.AddSeconds(15.0))
{
lock (_progressLock)
@ -354,23 +366,32 @@ internal sealed class QuestController : MiniTaskController<QuestController>
UpdateCurrentTask();
}
return;
IL_02de:
IL_0422:
flag = flag2;
goto IL_02e2;
goto IL_0426;
}
private void CheckAutoRefreshCondition()
{
if (!_configuration.General.AutoStepRefreshEnabled || AutomationType != EAutomationType.Automatic || !IsRunning || CurrentQuest == null || !_clientState.IsLoggedIn || _clientState.LocalPlayer == null || DateTime.Now < _lastAutoRefresh.AddSeconds(5.0))
if (!ShouldCheckAutoRefresh() || DateTime.Now < _lastAutoRefresh.AddSeconds(5.0))
{
return;
}
if (_condition[ConditionFlag.InCombat] || _condition[ConditionFlag.Unconscious] || _condition[ConditionFlag.BoundByDuty] || _condition[ConditionFlag.InDeepDungeon] || _condition[ConditionFlag.WatchingCutscene] || _condition[ConditionFlag.WatchingCutscene78] || _condition[ConditionFlag.BetweenAreas] || _condition[ConditionFlag.BetweenAreas51] || _gameFunctions.IsOccupied() || _movementController.IsPathfinding || _movementController.IsPathRunning || !_movementController.IsNavmeshReady || _taskQueue.CurrentTaskExecutor?.CurrentTask.GetType().Namespace == typeof(WaitAtEnd).Namespace || DateTime.Now < _safeAnimationEnd)
if (ShouldPreventAutoRefresh())
{
_lastProgressUpdate = DateTime.Now;
return;
}
Vector3 position = _clientState.LocalPlayer.Position;
IPlayerCharacter localPlayer = _clientState.LocalPlayer;
if (localPlayer == null)
{
return;
}
Vector3 position = localPlayer.Position;
if (CurrentQuest == null)
{
return;
}
ElementId id = CurrentQuest.Quest.Id;
byte sequence = CurrentQuest.Sequence;
int step = CurrentQuest.Step;
@ -395,6 +416,79 @@ internal sealed class QuestController : MiniTaskController<QuestController>
}
}
private bool ShouldCheckAutoRefresh()
{
if (_configuration.General.AutoStepRefreshEnabled && AutomationType == EAutomationType.Automatic && IsRunning && CurrentQuest != null && _clientState.IsLoggedIn)
{
return _clientState.LocalPlayer != null;
}
return false;
}
private bool ShouldPreventAutoRefresh()
{
if (HasWaitingTasks())
{
return true;
}
if (HasManualInterventionStep())
{
return true;
}
if (HasSystemConditionsPreventingRefresh())
{
return true;
}
if (HasConfigurationConditionsPreventingRefresh())
{
return true;
}
return false;
}
private bool HasWaitingTasks()
{
ITask task = _taskQueue.CurrentTaskExecutor?.CurrentTask;
if (task is WaitAtEnd.WaitObjectAtPosition || task is WaitAtEnd.WaitForCompletionFlags)
{
return true;
}
return false;
}
private bool HasManualInterventionStep()
{
switch (GetNextStep().Step?.InteractionType)
{
case EInteractionType.WaitForManualProgress:
case EInteractionType.Duty:
case EInteractionType.SinglePlayerDuty:
case EInteractionType.Snipe:
case EInteractionType.Instruction:
return true;
default:
return false;
}
}
private bool HasSystemConditionsPreventingRefresh()
{
if (_movementController.IsNavmeshReady && !_condition[ConditionFlag.InCombat] && !_condition[ConditionFlag.Unconscious] && !_condition[ConditionFlag.BoundByDuty] && !_condition[ConditionFlag.InDeepDungeon] && !_condition[ConditionFlag.WatchingCutscene] && !_condition[ConditionFlag.WatchingCutscene78] && !_condition[ConditionFlag.BetweenAreas] && !_condition[ConditionFlag.BetweenAreas51] && !_gameFunctions.IsOccupied() && !_movementController.IsPathfinding && !_movementController.IsPathRunning)
{
return DateTime.Now < _safeAnimationEnd;
}
return true;
}
private bool HasConfigurationConditionsPreventingRefresh()
{
if (_configuration.Advanced.PreventQuestCompletion)
{
return CurrentQuest?.Sequence == byte.MaxValue;
}
return false;
}
private void UpdateCurrentQuest()
{
lock (_progressLock)
@ -417,6 +511,20 @@ internal sealed class QuestController : MiniTaskController<QuestController>
_pendingQuest = null;
CheckNextTasks("Pending quest accepted");
}
if (_startedQuest != null && !_questFunctions.IsQuestAccepted(_startedQuest.Quest.Id))
{
if (_startedQuest.Quest.Info.IsRepeatable)
{
_logger.LogInformation("Repeatable quest {QuestId} is no longer accepted, clearing started quest", _startedQuest.Quest.Id);
}
else if (!_questFunctions.IsQuestComplete(_startedQuest.Quest.Id))
{
_logger.LogInformation("Quest {QuestId} was abandoned, clearing started quest", _startedQuest.Quest.Id);
_startedQuest = null;
Stop("Quest abandoned");
return;
}
}
if (_simulatedQuest == null && _nextQuest != null && !((!_nextQuest.Quest.Info.IsRepeatable) ? (!_questFunctions.IsQuestAcceptedOrComplete(_nextQuest.Quest.Id)) : (!_questFunctions.IsQuestAccepted(_nextQuest.Quest.Id))))
{
_logger.LogInformation("Next quest {QuestId} accepted or completed", _nextQuest.Quest.Id);
@ -425,21 +533,37 @@ internal sealed class QuestController : MiniTaskController<QuestController>
_startedQuest = _nextQuest;
AutomationType = EAutomationType.SingleQuestB;
}
else if (_questFunctions.IsQuestAccepted(_nextQuest.Quest.Id))
{
QuestProgressInfo questProgressInfo = _questFunctions.GetQuestProgressInfo(_nextQuest.Quest.Id);
if (questProgressInfo != null)
{
_startedQuest = new QuestProgress(_nextQuest.Quest, questProgressInfo.Sequence);
_logger.LogInformation("Moving accepted next quest to started quest (sequence: {Sequence})", questProgressInfo.Sequence);
_nextQuest = null;
CheckNextTasks("Next quest already accepted");
return;
}
_logger.LogWarning("Could not get quest progress info for accepted quest {QuestId}", _nextQuest.Quest.Id);
}
_logger.LogDebug("Started: {StartedQuest}", _startedQuest?.Quest.Id);
_nextQuest = null;
}
byte b;
QuestProgress questProgress;
ElementId CurrentQuest;
byte Sequence;
MainScenarioQuestState State;
if (_simulatedQuest != null)
{
b = _simulatedQuest.Sequence;
questProgress = _simulatedQuest;
}
else if (_nextQuest != null && _questFunctions.IsReadyToAcceptQuest(_nextQuest.Quest.Id))
else if (_nextQuest != null)
{
questProgress = _nextQuest;
b = _nextQuest.Sequence;
if (_nextQuest.Step == 0 && _taskQueue.AllTasksComplete && AutomationType == EAutomationType.Automatic)
if (_questFunctions.IsReadyToAcceptQuest(_nextQuest.Quest.Id) && _nextQuest.Step == 0 && _taskQueue.AllTasksComplete && AutomationType == EAutomationType.Automatic)
{
ExecuteNextStep();
}
@ -453,24 +577,71 @@ internal sealed class QuestController : MiniTaskController<QuestController>
ExecuteNextStep();
}
}
else
else if (_startedQuest != null)
{
_questFunctions.GetCurrentQuest(AutomationType != EAutomationType.SingleQuestB).Deconstruct(out ElementId CurrentQuest, out byte Sequence, out MainScenarioQuestState State);
ElementId elementId = CurrentQuest;
b = Sequence;
MainScenarioQuestState mainScenarioQuestState = State;
(ElementId, byte)? tuple = (from x in ManualPriorityQuests
where _questFunctions.IsReadyToAcceptQuest(x.Id) || _questFunctions.IsQuestAccepted(x.Id)
select (Id: x.Id, _questFunctions.GetQuestProgressInfo(x.Id)?.Sequence ?? 0)).FirstOrDefault();
if (tuple.HasValue)
questProgress = _startedQuest;
b = _startedQuest.Sequence;
QuestProgressInfo questProgressInfo2 = _questFunctions.GetQuestProgressInfo(_startedQuest.Quest.Id);
if (questProgressInfo2 != null && questProgressInfo2.Sequence != b)
{
(ElementId, byte) valueOrDefault = tuple.GetValueOrDefault();
if ((object)valueOrDefault.Item1 != null)
_logger.LogInformation("Updating started quest sequence from {OldSequence} to {NewSequence}", b, questProgressInfo2.Sequence);
b = questProgressInfo2.Sequence;
}
if (AutomationType == EAutomationType.Manual || !IsRunning)
{
_questFunctions.GetCurrentQuest(AutomationType != EAutomationType.SingleQuestB).Deconstruct(out CurrentQuest, out Sequence, out State);
ElementId elementId = CurrentQuest;
byte sequence = Sequence;
(ElementId, byte)? tuple = (from x in ManualPriorityQuests
where _questFunctions.IsReadyToAcceptQuest(x.Id) || _questFunctions.IsQuestAccepted(x.Id)
select (Id: x.Id, _questFunctions.GetQuestProgressInfo(x.Id)?.Sequence ?? 0)).FirstOrDefault();
if (tuple.HasValue)
{
(elementId, b) = valueOrDefault;
(ElementId, byte) valueOrDefault = tuple.GetValueOrDefault();
if ((object)valueOrDefault.Item1 != null)
{
(elementId, sequence) = valueOrDefault;
}
}
if (elementId != null && elementId.Value != 0 && _startedQuest.Quest.Id != elementId)
{
_logger.LogInformation("Game current quest changed from {OldQuest} to {NewQuest}, updating started quest", _startedQuest.Quest.Id, elementId);
if (_questRegistry.TryGetQuest(elementId, out Quest quest))
{
_logger.LogInformation("Switching to new quest: {QuestName}", quest.Info.Name);
_startedQuest = new QuestProgress(quest, sequence);
if (_clientState.LocalPlayer != null && _clientState.LocalPlayer.Level < quest.Info.Level)
{
_logger.LogInformation("Stopping automation, player level ({PlayerLevel}) < quest level ({QuestLevel}", _clientState.LocalPlayer.Level, quest.Info.Level);
Stop("Quest level too high");
}
questProgress = _startedQuest;
}
else
{
_logger.LogInformation("New quest {QuestId} not found in registry", elementId);
}
}
}
if (elementId == null || elementId.Value == 0)
}
else
{
_questFunctions.GetCurrentQuest(AutomationType != EAutomationType.SingleQuestB).Deconstruct(out CurrentQuest, out Sequence, out State);
ElementId elementId2 = CurrentQuest;
b = Sequence;
MainScenarioQuestState mainScenarioQuestState = State;
(ElementId, byte)? tuple3 = (from x in ManualPriorityQuests
where _questFunctions.IsReadyToAcceptQuest(x.Id) || _questFunctions.IsQuestAccepted(x.Id)
select (Id: x.Id, _questFunctions.GetQuestProgressInfo(x.Id)?.Sequence ?? 0)).FirstOrDefault();
if (tuple3.HasValue)
{
(ElementId, byte) valueOrDefault2 = tuple3.GetValueOrDefault();
if ((object)valueOrDefault2.Item1 != null)
{
(elementId2, b) = valueOrDefault2;
}
}
if (elementId2 == null || elementId2.Value == 0)
{
if (_startedQuest != null)
{
@ -491,9 +662,9 @@ internal sealed class QuestController : MiniTaskController<QuestController>
}
else
{
if (_startedQuest == null || _startedQuest.Quest.Id != elementId)
if (_startedQuest == null || _startedQuest.Quest.Id != elementId2)
{
Quest quest;
Quest quest2;
if (_configuration.Stop.Enabled && _startedQuest != null && _configuration.Stop.QuestsToStopAfter.Contains(_startedQuest.Quest.Id) && _questFunctions.IsQuestComplete(_startedQuest.Quest.Id))
{
ElementId id = _startedQuest.Quest.Id;
@ -502,13 +673,13 @@ internal sealed class QuestController : MiniTaskController<QuestController>
_startedQuest = null;
Stop($"Stopping point [{id}] reached");
}
else if (_questRegistry.TryGetQuest(elementId, out quest))
else if (_questRegistry.TryGetQuest(elementId2, out quest2))
{
_logger.LogInformation("New quest: {QuestName}", quest.Info.Name);
_startedQuest = new QuestProgress(quest, b);
if (_clientState.LocalPlayer != null && _clientState.LocalPlayer.Level < quest.Info.Level)
_logger.LogInformation("New quest: {QuestName}", quest2.Info.Name);
_startedQuest = new QuestProgress(quest2, b);
if (_clientState.LocalPlayer != null && _clientState.LocalPlayer.Level < quest2.Info.Level)
{
_logger.LogInformation("Stopping automation, player level ({PlayerLevel}) < quest level ({QuestLevel}", _clientState.LocalPlayer.Level, quest.Info.Level);
_logger.LogInformation("Stopping automation, player level ({PlayerLevel}) < quest level ({QuestLevel}", _clientState.LocalPlayer.Level, quest2.Info.Level);
Stop("Quest level too high");
return;
}
@ -533,7 +704,10 @@ internal sealed class QuestController : MiniTaskController<QuestController>
if (questProgress == null)
{
DebugState = "No quest active";
Stop("No quest active");
if (!IsRunning)
{
Stop("No quest active");
}
return;
}
if (_gameFunctions.IsOccupied() && !_gameFunctions.IsOccupiedWithCustomDeliveryNpc(questProgress.Quest))
@ -739,6 +913,13 @@ internal sealed class QuestController : MiniTaskController<QuestController>
}
}
public void SetStartedQuest(Quest quest, byte sequence = 0)
{
_logger.LogInformation("Setting started quest: {QuestId}", quest.Id);
_startedQuest = new QuestProgress(quest, sequence);
_nextQuest = null;
}
public void SetGatheringQuest(Quest? quest)
{
_logger.LogInformation("GatheringQuest: {QuestId}", quest?.Id);