105 lines
3.5 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|