Various tiny fixes for issues introduced in 0.6

arr-p5 v0.7
Liza 2024-06-09 22:44:35 +02:00
parent 5332247103
commit 73fef2677e
Signed by: liza
GPG Key ID: 7199F8D727D55F67
11 changed files with 97 additions and 48 deletions

View File

@ -99,7 +99,8 @@
"TerritoryId": 957, "TerritoryId": 957,
"InteractionType": "WalkTo", "InteractionType": "WalkTo",
"DisableNavmesh": true, "DisableNavmesh": true,
"Mount": true "Mount": true,
"Comment": "FIXME Returning to the surface means navmesh won't move anymore, but the path is still 'running'"
}, },
{ {
"Position": { "Position": {

View File

@ -34,7 +34,6 @@
"[Crystarium] The Cabinet of Curiosity", "[Crystarium] The Cabinet of Curiosity",
"[Crystarium] The Dossal Gate" "[Crystarium] The Dossal Gate"
], ],
"Comment": "TODO Check target territory id",
"TargetTerritoryId": 844 "TargetTerritoryId": 844
} }
] ]
@ -63,7 +62,7 @@
null, null,
null, null,
null, null,
16 -16
] ]
}, },
{ {

View File

@ -173,7 +173,10 @@ internal sealed class MovementController : IDisposable
ResetPathfinding(); ResetPathfinding();
if (InputManager.IsAutoRunning()) if (InputManager.IsAutoRunning())
{
_logger.LogInformation("Turning off auto-move");
_gameFunctions.ExecuteCommand("/automove off"); _gameFunctions.ExecuteCommand("/automove off");
}
Destination = new DestinationData(dataId, to, stopDistance ?? (DefaultStopDistance - 0.2f), fly, sprint); Destination = new DestinationData(dataId, to, stopDistance ?? (DefaultStopDistance - 0.2f), fly, sprint);
MovementStartedAt = DateTime.MaxValue; MovementStartedAt = DateTime.MaxValue;
@ -227,7 +230,10 @@ internal sealed class MovementController : IDisposable
ResetPathfinding(); ResetPathfinding();
if (InputManager.IsAutoRunning()) if (InputManager.IsAutoRunning())
{
_logger.LogInformation("Turning off auto-move [stop]");
_gameFunctions.ExecuteCommand("/automove off"); _gameFunctions.ExecuteCommand("/automove off");
}
} }
public void Dispose() public void Dispose()

View File

@ -108,9 +108,19 @@ internal static class AethernetShortcut
return ETaskResult.StillRunning; return ETaskResult.StillRunning;
} }
if (aetheryteData.CalculateDistance(clientState.LocalPlayer?.Position ?? Vector3.Zero, if (aetheryteData.IsCityAetheryte(To))
clientState.TerritoryType, To) > 11) {
return ETaskResult.StillRunning; if (aetheryteData.CalculateDistance(clientState.LocalPlayer?.Position ?? Vector3.Zero,
clientState.TerritoryType, To) > 11)
return ETaskResult.StillRunning;
}
else
{
// some overworld location (e.g. 'Tesselation (Lakeland)' would end up here
if (clientState.TerritoryType != aetheryteData.TerritoryIds[To])
return ETaskResult.StillRunning;
}
return ETaskResult.TaskComplete; return ETaskResult.TaskComplete;
} }

View File

@ -13,7 +13,10 @@ namespace Questionable.Controller.Steps.BaseFactory;
internal static class AetheryteShortcut internal static class AetheryteShortcut
{ {
internal sealed class Factory(IServiceProvider serviceProvider, GameFunctions gameFunctions) : ITaskFactory internal sealed class Factory(
IServiceProvider serviceProvider,
GameFunctions gameFunctions,
AetheryteData aetheryteData) : ITaskFactory
{ {
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step) public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
{ {
@ -21,7 +24,7 @@ internal static class AetheryteShortcut
return []; return [];
var task = serviceProvider.GetRequiredService<UseAetheryteShortcut>() var task = serviceProvider.GetRequiredService<UseAetheryteShortcut>()
.With(step, step.AetheryteShortcut.Value); .With(step, step.AetheryteShortcut.Value, aetheryteData.TerritoryIds[step.AetheryteShortcut.Value]);
return [new WaitConditionTask(gameFunctions.CanTeleport, "CanTeleport"), task]; return [new WaitConditionTask(gameFunctions.CanTeleport, "CanTeleport"), task];
} }
@ -41,10 +44,17 @@ internal static class AetheryteShortcut
public QuestStep Step { get; set; } = null!; public QuestStep Step { get; set; } = null!;
public EAetheryteLocation TargetAetheryte { get; set; } public EAetheryteLocation TargetAetheryte { get; set; }
public ITask With(QuestStep step, EAetheryteLocation targetAetheryte) /// <summary>
/// If using an aethernet shortcut after, the aetheryte's territory-id and the step's territory-id can differ,
/// we always use the aetheryte's territory-id.
/// </summary>
public ushort ExpectedTerritoryId { get; set; }
public ITask With(QuestStep step, EAetheryteLocation targetAetheryte, ushort expectedTerritoryId)
{ {
Step = step; Step = step;
TargetAetheryte = targetAetheryte; TargetAetheryte = targetAetheryte;
ExpectedTerritoryId = expectedTerritoryId;
return this; return this;
} }
@ -52,7 +62,7 @@ internal static class AetheryteShortcut
{ {
_continueAt = DateTime.Now.AddSeconds(8); _continueAt = DateTime.Now.AddSeconds(8);
ushort territoryType = clientState.TerritoryType; ushort territoryType = clientState.TerritoryType;
if (Step.TerritoryId == territoryType) if (ExpectedTerritoryId == territoryType)
{ {
Vector3 pos = clientState.LocalPlayer!.Position; Vector3 pos = clientState.LocalPlayer!.Position;
if (aetheryteData.CalculateDistance(pos, territoryType, TargetAetheryte) < 11 || if (aetheryteData.CalculateDistance(pos, territoryType, TargetAetheryte) < 11 ||
@ -84,8 +94,7 @@ internal static class AetheryteShortcut
public ETaskResult Update() public ETaskResult Update()
{ {
if (DateTime.Now >= _continueAt && clientState.TerritoryType == ExpectedTerritoryId)
if (DateTime.Now >= _continueAt && clientState.TerritoryType == Step.TerritoryId)
return ETaskResult.TaskComplete; return ETaskResult.TaskComplete;
return ETaskResult.StillRunning; return ETaskResult.StillRunning;

View File

@ -60,8 +60,10 @@ internal static class Move
yield break; yield break;
} }
yield return new WaitConditionTask(() => clientState.TerritoryType == Step.TerritoryId, $"Wait(territory: {Step.TerritoryId}"); yield return new WaitConditionTask(() => clientState.TerritoryType == Step.TerritoryId,
yield return new WaitConditionTask(() => movementController.IsNavmeshReady, "Wait(navmesh ready)"); $"Wait(territory: {Step.TerritoryId})");
yield return new WaitConditionTask(() => movementController.IsNavmeshReady,
"Wait(navmesh ready)");
float distance; float distance;
if (Step.InteractionType == EInteractionType.WalkTo) if (Step.InteractionType == EInteractionType.WalkTo)

View File

@ -13,7 +13,7 @@ internal static class Say
{ {
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step) public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
{ {
if (step.InteractionType != EInteractionType.Emote) if (step.InteractionType != EInteractionType.Say)
return []; return [];

View File

@ -10,6 +10,29 @@ namespace Questionable.Data;
internal sealed class AetheryteData internal sealed class AetheryteData
{ {
public AetheryteData(IDataManager dataManager)
{
Dictionary<EAetheryteLocation, string> aethernetNames = new();
Dictionary<EAetheryteLocation, ushort> territoryIds = new();
foreach (var aetheryte in dataManager.GetExcelSheet<Aetheryte>()!.Where(x => x.RowId > 0))
{
string? aethernetName = aetheryte.AethernetName?.Value?.Name.ToString();
if (!string.IsNullOrEmpty(aethernetName))
aethernetNames[(EAetheryteLocation)aetheryte.RowId] = aethernetName;
if (aetheryte.Territory != null && aetheryte.Territory.Row > 0)
territoryIds[(EAetheryteLocation)aetheryte.RowId] = (ushort)aetheryte.Territory.Row;
}
AethernetNames = aethernetNames.AsReadOnly();
TerritoryIds = territoryIds.AsReadOnly();
TownTerritoryIds = dataManager.GetExcelSheet<TerritoryType>()!
.Where(x => x.RowId > 0 && !string.IsNullOrEmpty(x.Name) && x.TerritoryIntendedUse == 0)
.Select(x => (ushort)x.RowId)
.ToList();
}
public ReadOnlyDictionary<EAetheryteLocation, Vector3> Locations { get; } = public ReadOnlyDictionary<EAetheryteLocation, Vector3> Locations { get; } =
new Dictionary<EAetheryteLocation, Vector3> new Dictionary<EAetheryteLocation, Vector3>
{ {
@ -196,24 +219,7 @@ internal sealed class AetheryteData
public ReadOnlyDictionary<EAetheryteLocation, string> AethernetNames { get; } public ReadOnlyDictionary<EAetheryteLocation, string> AethernetNames { get; }
public ReadOnlyDictionary<EAetheryteLocation, ushort> TerritoryIds { get; } public ReadOnlyDictionary<EAetheryteLocation, ushort> TerritoryIds { get; }
public IReadOnlyList<ushort> TownTerritoryIds { get; set; }
public AetheryteData(IDataManager dataManager)
{
Dictionary<EAetheryteLocation, string> aethernetNames = new();
Dictionary<EAetheryteLocation, ushort> territoryIds = new();
foreach (var aetheryte in dataManager.GetExcelSheet<Aetheryte>()!.Where(x => x.RowId > 0))
{
string? aethernetName = aetheryte.AethernetName?.Value?.Name.ToString();
if (!string.IsNullOrEmpty(aethernetName))
aethernetNames[(EAetheryteLocation)aetheryte.RowId] = aethernetName;
if (aetheryte.Territory != null && aetheryte.Territory.Row > 0)
territoryIds[(EAetheryteLocation)aetheryte.RowId] = (ushort)aetheryte.Territory.Row;
}
AethernetNames = aethernetNames.AsReadOnly();
TerritoryIds = territoryIds.AsReadOnly();
}
public float CalculateDistance(Vector3 fromPosition, ushort fromTerritoryType, EAetheryteLocation to) public float CalculateDistance(Vector3 fromPosition, ushort fromTerritoryType, EAetheryteLocation to)
{ {
@ -225,4 +231,10 @@ internal sealed class AetheryteData
return (fromPosition - toPosition).Length(); return (fromPosition - toPosition).Length();
} }
public bool IsCityAetheryte(EAetheryteLocation aetheryte)
{
var territoryId = TerritoryIds[aetheryte];
return TownTerritoryIds.Contains(territoryId);
}
} }

View File

@ -441,16 +441,26 @@ internal sealed unsafe class GameFunctions
{ {
if (ActionManager.Instance()->GetActionStatus(ActionType.Mount, 71) == 0) if (ActionManager.Instance()->GetActionStatus(ActionType.Mount, 71) == 0)
{ {
_logger.LogInformation("Using SDS Fenrir as mount"); if (ActionManager.Instance()->UseAction(ActionType.Mount, 71))
return ActionManager.Instance()->UseAction(ActionType.Mount, 71); {
_logger.LogInformation("Using SDS Fenrir as mount");
return true;
}
return false;
} }
} }
else else
{ {
if (ActionManager.Instance()->GetActionStatus(ActionType.GeneralAction, 9) == 0) if (ActionManager.Instance()->GetActionStatus(ActionType.GeneralAction, 9) == 0)
{ {
_logger.LogInformation("Using mount roulette"); if (ActionManager.Instance()->UseAction(ActionType.GeneralAction, 9))
return ActionManager.Instance()->UseAction(ActionType.GeneralAction, 9); {
_logger.LogInformation("Using mount roulette");
return true;
}
return false;
} }
} }
@ -485,14 +495,17 @@ internal sealed unsafe class GameFunctions
contentFinderConditionId, contentId); contentFinderConditionId, contentId);
} }
else else
_logger.LogError("Could not find content for content finder condition (cf: {ContentFinderId})", contentFinderConditionId); _logger.LogError("Could not find content for content finder condition (cf: {ContentFinderId})",
contentFinderConditionId);
} }
public string? GetDialogueText(Quest currentQuest, string? excelSheetName, string key) public string? GetDialogueText(Quest currentQuest, string? excelSheetName, string key)
{ {
if (excelSheetName == null) if (excelSheetName == null)
{ {
var questRow = _dataManager.GetExcelSheet<Lumina.Excel.GeneratedSheets2.Quest>()!.GetRow((uint)currentQuest.QuestId + 0x10000); var questRow =
_dataManager.GetExcelSheet<Lumina.Excel.GeneratedSheets2.Quest>()!.GetRow((uint)currentQuest.QuestId +
0x10000);
if (questRow == null) if (questRow == null)
{ {
_logger.LogError("Could not find quest row for {QuestId}", currentQuest.QuestId); _logger.LogError("Could not find quest row for {QuestId}", currentQuest.QuestId);
@ -526,10 +539,10 @@ internal sealed unsafe class GameFunctions
return true; return true;
return _condition[ConditionFlag.Occupied] || _condition[ConditionFlag.Occupied30] || return _condition[ConditionFlag.Occupied] || _condition[ConditionFlag.Occupied30] ||
_condition[ConditionFlag.Occupied33] || _condition[ConditionFlag.Occupied38] || _condition[ConditionFlag.Occupied33] || _condition[ConditionFlag.Occupied38] ||
_condition[ConditionFlag.Occupied39] || _condition[ConditionFlag.OccupiedInEvent] || _condition[ConditionFlag.Occupied39] || _condition[ConditionFlag.OccupiedInEvent] ||
_condition[ConditionFlag.OccupiedInQuestEvent] || _condition[ConditionFlag.OccupiedInCutSceneEvent] || _condition[ConditionFlag.OccupiedInQuestEvent] || _condition[ConditionFlag.OccupiedInCutSceneEvent] ||
_condition[ConditionFlag.Casting] || _condition[ConditionFlag.Unknown57] || _condition[ConditionFlag.Casting] || _condition[ConditionFlag.Unknown57] ||
_condition[ConditionFlag.BetweenAreas] || _condition[ConditionFlag.BetweenAreas51]; _condition[ConditionFlag.BetweenAreas] || _condition[ConditionFlag.BetweenAreas51];
} }
} }

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.6</Version> <Version>0.7</Version>
<LangVersion>12</LangVersion> <LangVersion>12</LangVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

View File

@ -92,9 +92,6 @@ public sealed class QuestionablePlugin : IDalamudPlugin
serviceCollection.AddTaskWithFactory<Say.Factory, Say.UseChat>(); serviceCollection.AddTaskWithFactory<Say.Factory, Say.UseChat>();
serviceCollection.AddTaskWithFactory<UseItem.Factory, UseItem.UseOnGround, UseItem.UseOnObject, UseItem.Use>(); serviceCollection.AddTaskWithFactory<UseItem.Factory, UseItem.UseOnGround, UseItem.UseOnObject, UseItem.Use>();
// TODO sort this in properly
serviceCollection.AddTaskWithFactory<ZoneChange.Factory, ZoneChange.WaitForZone>();
serviceCollection serviceCollection
.AddTaskWithFactory<WaitAtEnd.Factory, .AddTaskWithFactory<WaitAtEnd.Factory,
WaitAtEnd.WaitDelay, WaitAtEnd.WaitDelay,