153 lines
4.3 KiB
C#
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;
|
|
}
|
|
}
|