Skip to content

Commit

Permalink
Update algorithm for AFK timer to be accurate to EO main
Browse files Browse the repository at this point in the history
  • Loading branch information
ethanmoffat committed May 5, 2023
1 parent 920dafa commit ebcb528
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 22 deletions.
4 changes: 4 additions & 0 deletions EOLib.Localization/EOResourceID.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ public enum EOResourceID
DIALOG_PERFORMANCE_BEST_KILL = 293,
DIALOG_PERFORMANCE_LAST_KILL = 294,

IDLE_TOO_LONG = 295,
IDLE_PLEASE_START_MOVING = 296,


SKILLMASTER_WORD_SPELL = 297,
SKILLMASTER_WORD_SKILL = 298,
SPELL_WAS_SELECTED = 299,
Expand Down
8 changes: 6 additions & 2 deletions EndlessClient/HUD/Controls/HudControlsFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ public class HudControlsFactory : IHudControlsFactory
private readonly INewsProvider _newsProvider;
private readonly IFixedTimeStepRepository _fixedTimeStepRepository;
private readonly IClickDispatcherFactory _clickDispatcherFactory;

private IChatController _chatController;
private IMainButtonController _mainButtonController;

public HudControlsFactory(IHudButtonController hudButtonController,
IHudPanelFactory hudPanelFactory,
Expand Down Expand Up @@ -130,9 +132,11 @@ public HudControlsFactory(IHudButtonController hudButtonController,
_clickDispatcherFactory = clickDispatcherFactory;
}

public void InjectChatController(IChatController chatController)
public void InjectChatController(IChatController chatController,
IMainButtonController mainButtonController)
{
_chatController = chatController;
_mainButtonController = mainButtonController;
}

public IReadOnlyDictionary<HudControlIdentifier, IGameComponent> CreateHud()
Expand Down Expand Up @@ -567,7 +571,7 @@ private INPCAnimator CreateNPCAnimator()

private IPeriodicEmoteHandler CreatePeriodicEmoteHandler(ICharacterAnimator characterAnimator)
{
return new PeriodicEmoteHandler(_endlessGameProvider, _characterActions, _userInputTimeProvider, _characterRepository, characterAnimator);
return new PeriodicEmoteHandler(_endlessGameProvider, _characterActions, _userInputTimeProvider, _characterRepository, characterAnimator, _statusLabelSetter, _mainButtonController);
}

private PreviousUserInputTracker CreatePreviousUserInputTracker()
Expand Down
2 changes: 1 addition & 1 deletion EndlessClient/HUD/Controls/IHudControlsFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace EndlessClient.HUD.Controls
{
public interface IHudControlsFactory
{
void InjectChatController(IChatController chatController);
void InjectChatController(IChatController chatController, IMainButtonController mainButtonController);

IReadOnlyDictionary<HudControlIdentifier, IGameComponent> CreateHud();
}
Expand Down
2 changes: 1 addition & 1 deletion EndlessClient/Initialization/EndlessClientInitializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public void Initialize()
_characterManagementController);
_characterInfoPanelFactory.InjectCharacterManagementController(_characterManagementController);
_characterInfoPanelFactory.InjectLoginController(_loginController);
_hudControlsFactory.InjectChatController(_chatController);
_hudControlsFactory.InjectChatController(_chatController, _mainButtonController);
_paperdollDialogFactory.InjectInventoryController(_inventoryController);
}
}
Expand Down
100 changes: 82 additions & 18 deletions EndlessClient/Rendering/Character/PeriodicEmoteHandler.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using EndlessClient.GameExecution;
using EndlessClient.Controllers;
using EndlessClient.GameExecution;
using EndlessClient.HUD;
using EndlessClient.Input;
using EOLib.Domain.Character;
using EOLib.Localization;
using Microsoft.Xna.Framework;
using Optional;
using System;
Expand All @@ -10,13 +13,24 @@ namespace EndlessClient.Rendering.Character
{
public class PeriodicEmoteHandler : GameComponent, IPeriodicEmoteHandler
{
private const int AFK_TIME_MINUTES = 5;
private const int AFK_TIME_BETWEEN_EMOTES_MINUTES = 1;
// Time before periodic AFK emotes start firing (5 minutes)
private const int AFK_TIME_MS = 300000;
// Time between each emote once period emotes start firing (30 seconds)
private const int AFK_TIME_BETWEEN_EMOTES_MS = 30000;

// Time before periodic alert messages start firing (30 minutes)
private const int AFK_TIME_ALERT_MS = 1800000;
// Time between each periodic alert message fires (60 seconds)
private const int AFK_TIME_BETWEEN_ALERTS_MS = 60000;
// Time between first alert and alternate alert (3.6 seconds)
private const int AFK_TIME_ALT_ALERT_MS = 3600;

private readonly ICharacterActions _characterActions;
private readonly IUserInputTimeProvider _userInputTimeProvider;
private readonly ICharacterRepository _characterRepository;
private readonly ICharacterAnimator _animator;
private readonly IStatusLabelSetter _statusLabelSetter;
private readonly IMainButtonController _mainButtonController;

private readonly Random _random;

Expand All @@ -26,19 +40,24 @@ public class PeriodicEmoteHandler : GameComponent, IPeriodicEmoteHandler
private double _drunkTimeoutSeconds;

private Option<Stopwatch> _afkTimeSinceLastEmote;
private Option<Stopwatch> _afkTimeSinceLastAlert;
private bool _altAlert;

public PeriodicEmoteHandler(IEndlessGameProvider endlessGameProvider,
ICharacterActions characterActions,
IUserInputTimeProvider userInputTimeProvider,
ICharacterRepository characterRepository,
ICharacterAnimator animator)
ICharacterAnimator animator,
IStatusLabelSetter statusLabelSetter,
IMainButtonController mainButtonController)
: base((Game)endlessGameProvider.Game)
{
_characterActions = characterActions;
_userInputTimeProvider = userInputTimeProvider;
_characterRepository = characterRepository;
_animator = animator;

_statusLabelSetter = statusLabelSetter;
_mainButtonController = mainButtonController;
_random = new Random();
}

Expand Down Expand Up @@ -84,24 +103,69 @@ public override void Update(GameTime gameTime)
}
});

if ((DateTime.Now - _userInputTimeProvider.LastInputTime).TotalMinutes >= AFK_TIME_MINUTES)
var now = DateTime.Now;

if ((now - _userInputTimeProvider.LastInputTime).TotalMilliseconds >= AFK_TIME_MS)
{
_afkTimeSinceLastEmote.Match(
some: at =>
{
if (at.Elapsed.TotalMinutes >= AFK_TIME_BETWEEN_EMOTES_MINUTES)
if ((now - _userInputTimeProvider.LastInputTime).TotalMilliseconds >= AFK_TIME_MS + AFK_TIME_ALERT_MS)
{
_mainButtonController.GoToInitialStateAndDisconnect();
}
else
{
_afkTimeSinceLastEmote.Match(
some: at =>
{
if (_animator.Emote(_characterRepository.MainCharacter.ID, Emote.Moon))
if (at.ElapsedMilliseconds >= AFK_TIME_BETWEEN_EMOTES_MS)
{
_animator.Emote(_characterRepository.MainCharacter.ID, Emote.Moon);
_characterActions.Emote(Emote.Moon);
_afkTimeSinceLastEmote = Option.Some(Stopwatch.StartNew());
}
},
none: () =>
{
_animator.Emote(_characterRepository.MainCharacter.ID, Emote.Moon);
_characterActions.Emote(Emote.Moon);
_afkTimeSinceLastEmote = Option.Some(Stopwatch.StartNew());
}
},
none: () =>
});

if ((DateTime.Now - _userInputTimeProvider.LastInputTime).TotalMilliseconds >= AFK_TIME_ALERT_MS)
{
if (_animator.Emote(_characterRepository.MainCharacter.ID, Emote.Moon))
_characterActions.Emote(Emote.Moon);
_afkTimeSinceLastEmote = Option.Some(Stopwatch.StartNew());
});
_afkTimeSinceLastAlert.Match(
some: at =>
{
if (at.ElapsedMilliseconds >= AFK_TIME_BETWEEN_ALERTS_MS)
{
_statusLabelSetter.SetStatusLabel(EOResourceID.STATUS_LABEL_TYPE_WARNING, EOResourceID.IDLE_TOO_LONG);
_afkTimeSinceLastAlert = Option.Some(Stopwatch.StartNew());
_altAlert = false;
}
},
none: () =>
{
_statusLabelSetter.SetStatusLabel(EOResourceID.STATUS_LABEL_TYPE_WARNING, EOResourceID.IDLE_TOO_LONG);
_afkTimeSinceLastAlert = Option.Some(Stopwatch.StartNew());
_altAlert = false;
});

_afkTimeSinceLastAlert.Match(
some: at =>
{
if (at.ElapsedMilliseconds >= AFK_TIME_ALT_ALERT_MS && !_altAlert)
{
_statusLabelSetter.SetStatusLabel(EOResourceID.STATUS_LABEL_TYPE_WARNING, EOResourceID.IDLE_PLEASE_START_MOVING);
_altAlert = true;
}
},
none: () => _altAlert = false);
}
}
}
else
{
_afkTimeSinceLastEmote = Option.None<Stopwatch>();
_afkTimeSinceLastAlert = Option.None<Stopwatch>();
}

base.Update(gameTime);
Expand Down

0 comments on commit ebcb528

Please sign in to comment.