Files
xiv-plugins/AutoFishingStool/Plugin.cs

153 lines
4.3 KiB
C#

using System;
using Dalamud.Game.ClientState.Conditions;
using Dalamud.IoC;
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.System.String;
using FFXIVClientStructs.FFXIV.Client.UI;
namespace AutoFishingStool;
public sealed unsafe class Plugin : IDalamudPlugin
{
private const int SitDelayMilliseconds = 2500;
private const int ActionSettleMilliseconds = 500;
private const uint FisherClassJobId = 18;
[PluginService]
internal static ICondition Condition { get; private set; } = null!;
[PluginService]
internal static IFramework Framework { get; private set; } = null!;
[PluginService]
internal static IPlayerState PlayerState { get; private set; } = null!;
[PluginService]
internal static IPluginLog Log { get; private set; } = null!;
private DateTime? sitAt;
private bool satThisSession;
private bool waitingForActionToFinish;
public Plugin()
{
Condition.ConditionChange += OnConditionChange;
Framework.Update += OnFrameworkUpdate;
Log.Information("Auto Fishing Stool loaded");
}
private void OnConditionChange(ConditionFlag flag, bool value)
{
if (flag == ConditionFlag.Fishing)
{
Log.Information("Fishing condition changed to {Value}", value);
if (value && Condition[ConditionFlag.Gathering] && IsFisher() && !satThisSession)
{
sitAt = DateTime.UtcNow.AddMilliseconds(SitDelayMilliseconds);
waitingForActionToFinish = false;
Log.Information("Fishing became active; stable Sit timer started");
}
else if (!value && !satThisSession)
{
sitAt = null;
waitingForActionToFinish = false;
Log.Information("Fishing became inactive; stable Sit timer reset");
}
return;
}
if (flag != ConditionFlag.Gathering)
return;
Log.Information("Gathering condition changed to {Value}", value);
if (value)
{
if (!IsFisher())
return;
satThisSession = false;
sitAt = null;
waitingForActionToFinish = false;
Log.Information("Fisher gathering session started");
return;
}
sitAt = null;
satThisSession = false;
waitingForActionToFinish = false;
}
private void OnFrameworkUpdate(IFramework framework)
{
if (satThisSession || sitAt is null)
return;
if (!Condition[ConditionFlag.Gathering] || !Condition[ConditionFlag.Fishing] || !IsFisher())
{
sitAt = null;
satThisSession = false;
waitingForActionToFinish = false;
return;
}
if (DateTime.UtcNow < sitAt.Value)
return;
if (Condition[ConditionFlag.ExecutingGatheringAction])
{
if (!waitingForActionToFinish)
{
waitingForActionToFinish = true;
Log.Information("Sit timer elapsed during a fishing action; waiting for it to finish");
}
return;
}
if (waitingForActionToFinish)
{
waitingForActionToFinish = false;
sitAt = DateTime.UtcNow.AddMilliseconds(ActionSettleMilliseconds);
Log.Information("Fishing action finished; Sit command scheduled after settling");
return;
}
var uiModule = UIModule.Instance();
if (uiModule is null)
{
Log.Warning("Could not access the game's UI module");
sitAt = null;
return;
}
var command = Utf8String.FromString("/sit");
try
{
uiModule->ProcessChatBoxEntry(command);
Log.Information("Submitted /sit after fishing started");
}
finally
{
command->Dtor(true);
}
satThisSession = true;
sitAt = null;
waitingForActionToFinish = false;
}
private static bool IsFisher()
{
return PlayerState.IsLoaded && PlayerState.ClassJob.RowId == FisherClassJobId;
}
public void Dispose()
{
Condition.ConditionChange -= OnConditionChange;
Framework.Update -= OnFrameworkUpdate;
}
}