Skipping quest steps based on CompletionFlags now works

This commit is contained in:
Liza 2024-06-11 00:06:35 +02:00
parent a7459a628a
commit 97289c647f
Signed by: liza
GPG Key ID: 7199F8D727D55F67
11 changed files with 66 additions and 25 deletions

View File

@ -89,7 +89,7 @@
"Z": 419.7605 "Z": 419.7605
}, },
"TerritoryId": 959, "TerritoryId": 959,
"InteractionType": "Instruction", "InteractionType": "WaitForManualProgress",
"Comment": "Follow Argos" "Comment": "Follow Argos"
}, },
{ {
@ -148,7 +148,7 @@
"Z": 523.5217 "Z": 523.5217
}, },
"TerritoryId": 959, "TerritoryId": 959,
"InteractionType": "Instruction", "InteractionType": "WaitForManualProgress",
"Comment": "Follow Argos" "Comment": "Follow Argos"
}, },
{ {

View File

@ -110,18 +110,18 @@
"InteractionType": "Jump", "InteractionType": "Jump",
"JumpDestination": { "JumpDestination": {
"Position": { "Position": {
"X": -444.84818, "X": -443.62042,
"Y": -160.76439, "Y": -160.7644,
"Z": -645.7075 "Z": -644.7719
} }
}, },
"Comment": "Platform 4" "Comment": "Platform 4"
}, },
{ {
"Position": { "Position": {
"X": -444.84818, "X": -443.62042,
"Y": -160.76439, "Y": -160.7644,
"Z": -645.7075 "Z": -644.7719
}, },
"TerritoryId": 959, "TerritoryId": 959,
"InteractionType": "Jump", "InteractionType": "Jump",
@ -280,7 +280,8 @@
"Z": -620.05035 "Z": -620.05035
}, },
"TerritoryId": 959, "TerritoryId": 959,
"InteractionType": "Interact" "InteractionType": "Interact",
"Comment": "FIXME Auto-playing quests seems to get stuck here/do nothing"
} }
] ]
} }

View File

@ -129,8 +129,7 @@
"Z": 301.63266 "Z": 301.63266
}, },
"TerritoryId": 956, "TerritoryId": 956,
"InteractionType": "Interact", "InteractionType": "WalkTo"
"Comment": "TODO Should cancel navmesh if condition is [OccupiedInCutsceneEvent OR BetweenAreas]; then verify next marker distance"
} }
] ]
}, },

View File

@ -105,6 +105,23 @@
{ {
"Sequence": 5, "Sequence": 5,
"Steps": [ "Steps": [
{
"Position": {
"X": 26.119669,
"Y": 269.043,
"Z": -587.29144
},
"TerritoryId": 960,
"InteractionType": "WalkTo",
"CompletionQuestVariablesFlags": [
null,
null,
null,
null,
null,
-128
]
},
{ {
"DataId": 2012354, "DataId": 2012354,
"Position": { "Position": {

View File

@ -45,7 +45,7 @@
}, },
"TerritoryId": 960, "TerritoryId": 960,
"InteractionType": "WaitForManualProgress", "InteractionType": "WaitForManualProgress",
"Comment": "Identify Anomaly (Elbow/Knee)" "Comment": "Identify Anomaly (Head, Elbow or Knee)"
} }
] ]
}, },

View File

@ -112,6 +112,12 @@ internal sealed class MovementController : IDisposable
if (IsPathRunning && Destination != null) if (IsPathRunning && Destination != null)
{ {
if (_gameFunctions.IsLoadingScreenVisible())
{
Stop();
return;
}
Vector3 localPlayerPosition = _clientState.LocalPlayer?.Position ?? Vector3.Zero; Vector3 localPlayerPosition = _clientState.LocalPlayer?.Position ?? Vector3.Zero;
if ((localPlayerPosition - Destination.Position).Length() < Destination.StopDistance) if ((localPlayerPosition - Destination.Position).Length() < Destination.StopDistance)
{ {

View File

@ -76,7 +76,7 @@ internal static class SkipCondition
} }
QuestWork? questWork = gameFunctions.GetQuestEx(QuestId); QuestWork? questWork = gameFunctions.GetQuestEx(QuestId);
if (questWork != null && Step.MatchesQuestVariables(questWork.Value)) if (questWork != null && Step.MatchesQuestVariables(questWork.Value, true))
{ {
logger.LogInformation("Skipping step, as quest variables match"); logger.LogInformation("Skipping step, as quest variables match");
return true; return true;

View File

@ -18,7 +18,7 @@ internal static class WaitAtEnd
{ {
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step) public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
{ {
if (step.CompletionQuestVariablesFlags.Count == 6) if (step.CompletionQuestVariablesFlags.Count == 6 && step.CompletionQuestVariablesFlags.Any(x => x is > 0))
{ {
var task = serviceProvider.GetRequiredService<WaitForCompletionFlags>() var task = serviceProvider.GetRequiredService<WaitForCompletionFlags>()
.With(quest, step); .With(quest, step);
@ -129,7 +129,7 @@ internal static class WaitAtEnd
public ETaskResult Update() public ETaskResult Update()
{ {
QuestWork? questWork = gameFunctions.GetQuestEx(Quest.QuestId); QuestWork? questWork = gameFunctions.GetQuestEx(Quest.QuestId);
return questWork != null && Step.MatchesQuestVariables(questWork.Value) return questWork != null && Step.MatchesQuestVariables(questWork.Value, false)
? ETaskResult.TaskComplete ? ETaskResult.TaskComplete
: ETaskResult.StillRunning; : ETaskResult.StillRunning;
} }

View File

@ -534,9 +534,7 @@ internal sealed unsafe class GameFunctions
public bool IsOccupied() public bool IsOccupied()
{ {
if (_gameGui.TryGetAddonByName("FadeMiddle", out AtkUnitBase* fade) && if (IsLoadingScreenVisible())
LAddon.IsAddonReady(fade) &&
fade->IsVisible)
return true; return true;
return _condition[ConditionFlag.Occupied] || _condition[ConditionFlag.Occupied30] || return _condition[ConditionFlag.Occupied] || _condition[ConditionFlag.Occupied30] ||
@ -546,4 +544,11 @@ internal sealed unsafe class GameFunctions
_condition[ConditionFlag.Casting] || _condition[ConditionFlag.Unknown57] || _condition[ConditionFlag.Casting] || _condition[ConditionFlag.Unknown57] ||
_condition[ConditionFlag.BetweenAreas] || _condition[ConditionFlag.BetweenAreas51]; _condition[ConditionFlag.BetweenAreas] || _condition[ConditionFlag.BetweenAreas51];
} }
public bool IsLoadingScreenVisible()
{
return _gameGui.TryGetAddonByName("FadeMiddle", out AtkUnitBase* fade) &&
LAddon.IsAddonReady(fade) &&
fade->IsVisible;
}
} }

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Numerics; using System.Numerics;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
@ -50,7 +51,11 @@ internal sealed class QuestStep
public IList<short?> CompletionQuestVariablesFlags { get; set; } = new List<short?>(); public IList<short?> CompletionQuestVariablesFlags { get; set; } = new List<short?>();
public IList<DialogueChoice> DialogueChoices { get; set; } = new List<DialogueChoice>(); public IList<DialogueChoice> DialogueChoices { get; set; } = new List<DialogueChoice>();
public unsafe bool MatchesQuestVariables(QuestWork questWork) /// <summary>
/// Positive values: Must be set to this value; will wait for the step to have these set.
/// Negative values: Will skip if set to this value, won't wait for this to be set.
/// </summary>
public unsafe bool MatchesQuestVariables(QuestWork questWork, bool forSkip)
{ {
if (CompletionQuestVariablesFlags.Count != 6) if (CompletionQuestVariablesFlags.Count != 6)
return false; return false;
@ -62,11 +67,19 @@ internal sealed class QuestStep
continue; continue;
byte actualValue = questWork.Variables[i]; byte actualValue = questWork.Variables[i];
byte expectedValue = check > 0 ? (byte)check : (byte)0;
byte checkByte = check > 0 ? (byte)check : (byte)-check; byte checkByte = check > 0 ? (byte)check : (byte)-check;
if (forSkip)
if ((actualValue & checkByte) != expectedValue) {
return false; byte expectedValue = (byte)Math.Abs(check.Value);
if ((actualValue & checkByte) != expectedValue)
return false;
}
else if (!forSkip && check > 0)
{
byte expectedValue = check > 0 ? (byte)check : (byte)0;
if ((actualValue & checkByte) != expectedValue)
return false;
}
} }
return true; return true;

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework> <TargetFramework>net8.0-windows</TargetFramework>
<Version>0.8</Version> <Version>0.9</Version>
<LangVersion>12</LangVersion> <LangVersion>12</LangVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>