qstbak/Questionable/Questionable.Controller.Steps.Interactions/CriticalEncounter.cs
2026-08-17 20:29:32 +10:00

105 lines
3.5 KiB
C#

using System;
using System.Collections.Generic;
using LLib.GameData;
using Microsoft.Extensions.Logging;
using Questionable.Controller.Steps.Common;
using Questionable.Model;
using Questionable.Model.Questing;
namespace Questionable.Controller.Steps.Interactions;
internal static class CriticalEncounter
{
internal sealed class Factory : ITaskFactory
{
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
{
if (step.InteractionType != EInteractionType.CriticalEncounter)
{
return Array.Empty<ITask>();
}
ushort? criticalEncounterId = step.CriticalEncounterId;
if ((!criticalEncounterId.HasValue || criticalEncounterId.GetValueOrDefault() == 0) ? true : false)
{
throw new InvalidOperationException("CriticalEncounter step requires CriticalEncounterId");
}
return new global::_003C_003Ez__ReadOnlySingleElementList<ITask>(new WaitForCriticalEncounter(step.CriticalEncounterId.Value, step.Comment));
}
}
internal sealed record WaitForCriticalEncounter(ushort CriticalEncounterId, string? Comment) : ITask
{
public override string ToString()
{
return $"WaitForCriticalEncounter({CriticalEncounterId})";
}
}
internal sealed class WaitForCriticalEncounterExecutor(PublicEventHelper publicEventHelper, MovementController movementController, SendNotification.Executor sendNotificationExecutor, ILogger<WaitForCriticalEncounterExecutor> logger) : TaskExecutor<WaitForCriticalEncounter>()
{
private long _nextPollAt;
private bool _loggedWaiting;
private bool _notified;
private bool _navigating;
protected override bool Start()
{
logger.LogDebug("Waiting for critical encounter {Id}", base.Task.CriticalEncounterId);
return true;
}
public override ETaskResult Update()
{
if (Environment.TickCount64 < _nextPollAt)
{
return ETaskResult.StillRunning;
}
PublicEvent? eventById = publicEventHelper.GetEventById(EPublicEventType.DynamicEvent, base.Task.CriticalEncounterId);
if (eventById.HasValue)
{
PublicEvent valueOrDefault = eventById.GetValueOrDefault();
if (!_notified)
{
logger.LogInformation("Critical encounter {Id} ({Name}) is up", base.Task.CriticalEncounterId, valueOrDefault.Name);
sendNotificationExecutor.Start(new SendNotification.Task(EInteractionType.CriticalEncounter, base.Task.Comment ?? valueOrDefault.Name));
_notified = true;
}
eventById = publicEventHelper.GetCurrentDynamicEvent();
if (eventById.HasValue && eventById.GetValueOrDefault().Id == base.Task.CriticalEncounterId)
{
return ETaskResult.TaskComplete;
}
if (valueOrDefault.IsActive)
{
_nextPollAt = Environment.TickCount64 + 2000;
return ETaskResult.StillRunning;
}
if (!_navigating)
{
logger.LogInformation("Moving into critical encounter {Id} at {Position}", base.Task.CriticalEncounterId, valueOrDefault.Position);
movementController.NavigateTo(EMovementType.Quest, null, valueOrDefault.Position, fly: false, sprint: true, 5f);
_navigating = true;
}
_nextPollAt = Environment.TickCount64 + 1000;
return ETaskResult.StillRunning;
}
if (!_loggedWaiting)
{
logger.LogDebug("Critical encounter {Id} not active yet, waiting for spawn", base.Task.CriticalEncounterId);
_loggedWaiting = true;
}
_notified = false;
_navigating = false;
_nextPollAt = Environment.TickCount64 + 1000;
return ETaskResult.StillRunning;
}
public override bool ShouldInterruptOnDamage()
{
return false;
}
}
}