Add plugin setup window
This commit is contained in:
parent
ad76bb88c0
commit
bd38b330ed
2
LLib
2
LLib
@ -1 +1 @@
|
|||||||
Subproject commit 6dfc18ee6a187138036ee2d51ba2257741c1e568
|
Subproject commit 912a7b04ce180e337af9beeef2d1393b040c1ba8
|
@ -6,12 +6,19 @@ namespace Questionable;
|
|||||||
|
|
||||||
internal sealed class Configuration : IPluginConfiguration
|
internal sealed class Configuration : IPluginConfiguration
|
||||||
{
|
{
|
||||||
|
public const int PluginSetupVersion = 1;
|
||||||
|
|
||||||
public int Version { get; set; } = 1;
|
public int Version { get; set; } = 1;
|
||||||
|
public int PluginSetupCompleteVersion { get; set; }
|
||||||
public GeneralConfiguration General { get; } = new();
|
public GeneralConfiguration General { get; } = new();
|
||||||
public AdvancedConfiguration Advanced { get; } = new();
|
public AdvancedConfiguration Advanced { get; } = new();
|
||||||
public WindowConfig DebugWindowConfig { get; } = new();
|
public WindowConfig DebugWindowConfig { get; } = new();
|
||||||
public WindowConfig ConfigWindowConfig { get; } = new();
|
public WindowConfig ConfigWindowConfig { get; } = new();
|
||||||
|
|
||||||
|
internal bool IsPluginSetupComplete() => PluginSetupCompleteVersion == PluginSetupVersion;
|
||||||
|
|
||||||
|
internal void MarkPluginSetupComplete() => PluginSetupCompleteVersion = PluginSetupVersion;
|
||||||
|
|
||||||
internal sealed class GeneralConfiguration
|
internal sealed class GeneralConfiguration
|
||||||
{
|
{
|
||||||
public uint MountId { get; set; } = 71;
|
public uint MountId { get; set; } = 71;
|
||||||
|
@ -24,12 +24,14 @@ internal sealed class CommandHandler : IDisposable
|
|||||||
private readonly QuestRegistry _questRegistry;
|
private readonly QuestRegistry _questRegistry;
|
||||||
private readonly ConfigWindow _configWindow;
|
private readonly ConfigWindow _configWindow;
|
||||||
private readonly DebugOverlay _debugOverlay;
|
private readonly DebugOverlay _debugOverlay;
|
||||||
|
private readonly OneTimeSetupWindow _oneTimeSetupWindow;
|
||||||
private readonly QuestWindow _questWindow;
|
private readonly QuestWindow _questWindow;
|
||||||
private readonly QuestSelectionWindow _questSelectionWindow;
|
private readonly QuestSelectionWindow _questSelectionWindow;
|
||||||
private readonly ITargetManager _targetManager;
|
private readonly ITargetManager _targetManager;
|
||||||
private readonly QuestFunctions _questFunctions;
|
private readonly QuestFunctions _questFunctions;
|
||||||
private readonly GameFunctions _gameFunctions;
|
private readonly GameFunctions _gameFunctions;
|
||||||
private readonly IDataManager _dataManager;
|
private readonly IDataManager _dataManager;
|
||||||
|
private readonly Configuration _configuration;
|
||||||
|
|
||||||
public CommandHandler(
|
public CommandHandler(
|
||||||
ICommandManager commandManager,
|
ICommandManager commandManager,
|
||||||
@ -39,12 +41,14 @@ internal sealed class CommandHandler : IDisposable
|
|||||||
QuestRegistry questRegistry,
|
QuestRegistry questRegistry,
|
||||||
ConfigWindow configWindow,
|
ConfigWindow configWindow,
|
||||||
DebugOverlay debugOverlay,
|
DebugOverlay debugOverlay,
|
||||||
|
OneTimeSetupWindow oneTimeSetupWindow,
|
||||||
QuestWindow questWindow,
|
QuestWindow questWindow,
|
||||||
QuestSelectionWindow questSelectionWindow,
|
QuestSelectionWindow questSelectionWindow,
|
||||||
ITargetManager targetManager,
|
ITargetManager targetManager,
|
||||||
QuestFunctions questFunctions,
|
QuestFunctions questFunctions,
|
||||||
GameFunctions gameFunctions,
|
GameFunctions gameFunctions,
|
||||||
IDataManager dataManager)
|
IDataManager dataManager,
|
||||||
|
Configuration configuration)
|
||||||
{
|
{
|
||||||
_commandManager = commandManager;
|
_commandManager = commandManager;
|
||||||
_chatGui = chatGui;
|
_chatGui = chatGui;
|
||||||
@ -53,12 +57,14 @@ internal sealed class CommandHandler : IDisposable
|
|||||||
_questRegistry = questRegistry;
|
_questRegistry = questRegistry;
|
||||||
_configWindow = configWindow;
|
_configWindow = configWindow;
|
||||||
_debugOverlay = debugOverlay;
|
_debugOverlay = debugOverlay;
|
||||||
|
_oneTimeSetupWindow = oneTimeSetupWindow;
|
||||||
_questWindow = questWindow;
|
_questWindow = questWindow;
|
||||||
_questSelectionWindow = questSelectionWindow;
|
_questSelectionWindow = questSelectionWindow;
|
||||||
_targetManager = targetManager;
|
_targetManager = targetManager;
|
||||||
_questFunctions = questFunctions;
|
_questFunctions = questFunctions;
|
||||||
_gameFunctions = gameFunctions;
|
_gameFunctions = gameFunctions;
|
||||||
_dataManager = dataManager;
|
_dataManager = dataManager;
|
||||||
|
_configuration = configuration;
|
||||||
|
|
||||||
_commandManager.AddHandler("/qst", new CommandInfo(ProcessCommand)
|
_commandManager.AddHandler("/qst", new CommandInfo(ProcessCommand)
|
||||||
{
|
{
|
||||||
@ -75,6 +81,15 @@ internal sealed class CommandHandler : IDisposable
|
|||||||
|
|
||||||
private void ProcessCommand(string command, string arguments)
|
private void ProcessCommand(string command, string arguments)
|
||||||
{
|
{
|
||||||
|
if (!_configuration.IsPluginSetupComplete())
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(arguments))
|
||||||
|
_oneTimeSetupWindow.IsOpen = true;
|
||||||
|
else
|
||||||
|
_chatGui.PrintError("Please complete the one-time setup first.", MessageTag, TagColor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
string[] parts = arguments.Split(' ');
|
string[] parts = arguments.Split(' ');
|
||||||
switch (parts[0])
|
switch (parts[0])
|
||||||
{
|
{
|
||||||
|
@ -18,9 +18,11 @@ internal sealed class DalamudInitializer : IDisposable
|
|||||||
private readonly QuestController _questController;
|
private readonly QuestController _questController;
|
||||||
private readonly MovementController _movementController;
|
private readonly MovementController _movementController;
|
||||||
private readonly WindowSystem _windowSystem;
|
private readonly WindowSystem _windowSystem;
|
||||||
|
private readonly OneTimeSetupWindow _oneTimeSetupWindow;
|
||||||
private readonly QuestWindow _questWindow;
|
private readonly QuestWindow _questWindow;
|
||||||
private readonly ConfigWindow _configWindow;
|
private readonly ConfigWindow _configWindow;
|
||||||
private readonly IToastGui _toastGui;
|
private readonly IToastGui _toastGui;
|
||||||
|
private readonly Configuration _configuration;
|
||||||
private readonly ILogger<DalamudInitializer> _logger;
|
private readonly ILogger<DalamudInitializer> _logger;
|
||||||
|
|
||||||
public DalamudInitializer(
|
public DalamudInitializer(
|
||||||
@ -30,6 +32,7 @@ internal sealed class DalamudInitializer : IDisposable
|
|||||||
MovementController movementController,
|
MovementController movementController,
|
||||||
InteractionUiController interactionUiController,
|
InteractionUiController interactionUiController,
|
||||||
WindowSystem windowSystem,
|
WindowSystem windowSystem,
|
||||||
|
OneTimeSetupWindow oneTimeSetupWindow,
|
||||||
QuestWindow questWindow,
|
QuestWindow questWindow,
|
||||||
DebugOverlay debugOverlay,
|
DebugOverlay debugOverlay,
|
||||||
ConfigWindow configWindow,
|
ConfigWindow configWindow,
|
||||||
@ -38,6 +41,7 @@ internal sealed class DalamudInitializer : IDisposable
|
|||||||
JournalProgressWindow journalProgressWindow,
|
JournalProgressWindow journalProgressWindow,
|
||||||
PriorityWindow priorityWindow,
|
PriorityWindow priorityWindow,
|
||||||
IToastGui toastGui,
|
IToastGui toastGui,
|
||||||
|
Configuration configuration,
|
||||||
ILogger<DalamudInitializer> logger)
|
ILogger<DalamudInitializer> logger)
|
||||||
{
|
{
|
||||||
_pluginInterface = pluginInterface;
|
_pluginInterface = pluginInterface;
|
||||||
@ -45,11 +49,14 @@ internal sealed class DalamudInitializer : IDisposable
|
|||||||
_questController = questController;
|
_questController = questController;
|
||||||
_movementController = movementController;
|
_movementController = movementController;
|
||||||
_windowSystem = windowSystem;
|
_windowSystem = windowSystem;
|
||||||
|
_oneTimeSetupWindow = oneTimeSetupWindow;
|
||||||
_questWindow = questWindow;
|
_questWindow = questWindow;
|
||||||
_configWindow = configWindow;
|
_configWindow = configWindow;
|
||||||
_toastGui = toastGui;
|
_toastGui = toastGui;
|
||||||
|
_configuration = configuration;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
||||||
|
_windowSystem.AddWindow(oneTimeSetupWindow);
|
||||||
_windowSystem.AddWindow(questWindow);
|
_windowSystem.AddWindow(questWindow);
|
||||||
_windowSystem.AddWindow(configWindow);
|
_windowSystem.AddWindow(configWindow);
|
||||||
_windowSystem.AddWindow(debugOverlay);
|
_windowSystem.AddWindow(debugOverlay);
|
||||||
@ -59,7 +66,7 @@ internal sealed class DalamudInitializer : IDisposable
|
|||||||
_windowSystem.AddWindow(priorityWindow);
|
_windowSystem.AddWindow(priorityWindow);
|
||||||
|
|
||||||
_pluginInterface.UiBuilder.Draw += _windowSystem.Draw;
|
_pluginInterface.UiBuilder.Draw += _windowSystem.Draw;
|
||||||
_pluginInterface.UiBuilder.OpenMainUi += _questWindow.Toggle;
|
_pluginInterface.UiBuilder.OpenMainUi += ToggleQuestWindow;
|
||||||
_pluginInterface.UiBuilder.OpenConfigUi += _configWindow.Toggle;
|
_pluginInterface.UiBuilder.OpenConfigUi += _configWindow.Toggle;
|
||||||
_framework.Update += FrameworkUpdate;
|
_framework.Update += FrameworkUpdate;
|
||||||
_framework.RunOnTick(interactionUiController.HandleCurrentDialogueChoices, TimeSpan.FromMilliseconds(200));
|
_framework.RunOnTick(interactionUiController.HandleCurrentDialogueChoices, TimeSpan.FromMilliseconds(200));
|
||||||
@ -91,6 +98,14 @@ internal sealed class DalamudInitializer : IDisposable
|
|||||||
private void OnQuestToast(ref SeString message, ref QuestToastOptions options, ref bool isHandled)
|
private void OnQuestToast(ref SeString message, ref QuestToastOptions options, ref bool isHandled)
|
||||||
=> _logger.LogTrace("Quest Toast: {Message}", message);
|
=> _logger.LogTrace("Quest Toast: {Message}", message);
|
||||||
|
|
||||||
|
private void ToggleQuestWindow()
|
||||||
|
{
|
||||||
|
if (_configuration.IsPluginSetupComplete())
|
||||||
|
_questWindow.Toggle();
|
||||||
|
else
|
||||||
|
_oneTimeSetupWindow.IsOpen = true;
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_toastGui.QuestToast -= OnQuestToast;
|
_toastGui.QuestToast -= OnQuestToast;
|
||||||
@ -98,7 +113,7 @@ internal sealed class DalamudInitializer : IDisposable
|
|||||||
_toastGui.Toast -= OnToast;
|
_toastGui.Toast -= OnToast;
|
||||||
_framework.Update -= FrameworkUpdate;
|
_framework.Update -= FrameworkUpdate;
|
||||||
_pluginInterface.UiBuilder.OpenConfigUi -= _configWindow.Toggle;
|
_pluginInterface.UiBuilder.OpenConfigUi -= _configWindow.Toggle;
|
||||||
_pluginInterface.UiBuilder.OpenMainUi -= _questWindow.Toggle;
|
_pluginInterface.UiBuilder.OpenMainUi -= ToggleQuestWindow;
|
||||||
_pluginInterface.UiBuilder.Draw -= _windowSystem.Draw;
|
_pluginInterface.UiBuilder.Draw -= _windowSystem.Draw;
|
||||||
|
|
||||||
_windowSystem.RemoveAllWindows();
|
_windowSystem.RemoveAllWindows();
|
||||||
|
@ -6,6 +6,7 @@ using Dalamud.Game.ClientState.Objects;
|
|||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
|
using LLib;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Questionable.Controller;
|
using Questionable.Controller;
|
||||||
@ -110,6 +111,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
|||||||
serviceCollection.AddSingleton<GameFunctions>();
|
serviceCollection.AddSingleton<GameFunctions>();
|
||||||
serviceCollection.AddSingleton<ChatFunctions>();
|
serviceCollection.AddSingleton<ChatFunctions>();
|
||||||
serviceCollection.AddSingleton<QuestFunctions>();
|
serviceCollection.AddSingleton<QuestFunctions>();
|
||||||
|
serviceCollection.AddSingleton<DalamudReflector>();
|
||||||
serviceCollection.AddSingleton<AutoSnipeHandler>();
|
serviceCollection.AddSingleton<AutoSnipeHandler>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<AetherCurrentData>();
|
serviceCollection.AddSingleton<AetherCurrentData>();
|
||||||
@ -255,6 +257,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
|||||||
serviceCollection.AddSingleton<QuestJournalComponent>();
|
serviceCollection.AddSingleton<QuestJournalComponent>();
|
||||||
serviceCollection.AddSingleton<GatheringJournalComponent>();
|
serviceCollection.AddSingleton<GatheringJournalComponent>();
|
||||||
|
|
||||||
|
serviceCollection.AddSingleton<OneTimeSetupWindow>();
|
||||||
serviceCollection.AddSingleton<QuestWindow>();
|
serviceCollection.AddSingleton<QuestWindow>();
|
||||||
serviceCollection.AddSingleton<ConfigWindow>();
|
serviceCollection.AddSingleton<ConfigWindow>();
|
||||||
serviceCollection.AddSingleton<DebugOverlay>();
|
serviceCollection.AddSingleton<DebugOverlay>();
|
||||||
|
164
Questionable/Windows/OneTimeSetupWindow.cs
Normal file
164
Questionable/Windows/OneTimeSetupWindow.cs
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Dalamud.Interface;
|
||||||
|
using Dalamud.Interface.Colors;
|
||||||
|
using Dalamud.Interface.Components;
|
||||||
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
using Dalamud.Plugin;
|
||||||
|
using Dalamud.Utility;
|
||||||
|
using ImGuiNET;
|
||||||
|
using LLib;
|
||||||
|
using LLib.ImGui;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Questionable.Windows;
|
||||||
|
|
||||||
|
internal sealed class OneTimeSetupWindow : LWindow, IDisposable
|
||||||
|
{
|
||||||
|
private static readonly IReadOnlyList<PluginInfo> RequiredPlugins =
|
||||||
|
[
|
||||||
|
new("vnavmesh",
|
||||||
|
"""
|
||||||
|
vnavmesh handles the navigation within a zone, moving
|
||||||
|
your character to the next quest-related objective.
|
||||||
|
""",
|
||||||
|
new Uri("https://github.com/awgil/ffxiv_navmesh/")),
|
||||||
|
new("Lifestream",
|
||||||
|
"""
|
||||||
|
Used to travel to aethernet shards in cities.
|
||||||
|
""",
|
||||||
|
new Uri("https://github.com/NightmareXIV/Lifestream")),
|
||||||
|
new("TextAdvance",
|
||||||
|
"""
|
||||||
|
Automatically accepts and turns in quests, skips cutscenes
|
||||||
|
and dialogue.
|
||||||
|
""",
|
||||||
|
new Uri("https://github.com/NightmareXIV/TextAdvance")),
|
||||||
|
];
|
||||||
|
|
||||||
|
private static readonly IReadOnlyList<PluginInfo> RecommendedPlugins =
|
||||||
|
[
|
||||||
|
new("Rotation Solver Reborn",
|
||||||
|
"""
|
||||||
|
Automatically handles most combat interactions you encounter
|
||||||
|
during quests, including being interrupted by mobs.
|
||||||
|
""",
|
||||||
|
new Uri("https://github.com/FFXIV-CombatReborn/RotationSolverReborn")),
|
||||||
|
];
|
||||||
|
|
||||||
|
private readonly Configuration _configuration;
|
||||||
|
private readonly IDalamudPluginInterface _pluginInterface;
|
||||||
|
private readonly UiUtils _uiUtils;
|
||||||
|
private readonly DalamudReflector _dalamudReflector;
|
||||||
|
private readonly ILogger<OneTimeSetupWindow> _logger;
|
||||||
|
|
||||||
|
public OneTimeSetupWindow(Configuration configuration, IDalamudPluginInterface pluginInterface, UiUtils uiUtils,
|
||||||
|
DalamudReflector dalamudReflector, ILogger<OneTimeSetupWindow> logger)
|
||||||
|
: base("Questionable Setup###QuestionableOneTimeSetup",
|
||||||
|
ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoSavedSettings, true)
|
||||||
|
{
|
||||||
|
_configuration = configuration;
|
||||||
|
_pluginInterface = pluginInterface;
|
||||||
|
_uiUtils = uiUtils;
|
||||||
|
_dalamudReflector = dalamudReflector;
|
||||||
|
_logger = logger;
|
||||||
|
|
||||||
|
RespectCloseHotkey = false;
|
||||||
|
ShowCloseButton = false;
|
||||||
|
AllowPinning = false;
|
||||||
|
AllowClickthrough = false;
|
||||||
|
IsOpen = !_configuration.IsPluginSetupComplete();
|
||||||
|
_logger.LogInformation("One-time setup needed: {IsOpen}", IsOpen);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw()
|
||||||
|
{
|
||||||
|
float checklistPadding;
|
||||||
|
using (_pluginInterface.UiBuilder.IconFontFixedWidthHandle.Push())
|
||||||
|
{
|
||||||
|
checklistPadding = ImGui.CalcTextSize(FontAwesomeIcon.Check.ToIconString()).X +
|
||||||
|
ImGui.GetStyle().ItemSpacing.X;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.Text("Questionable requires the following plugins to work:");
|
||||||
|
bool allRequiredInstalled = true;
|
||||||
|
using (ImRaii.PushIndent())
|
||||||
|
{
|
||||||
|
foreach (var plugin in RequiredPlugins)
|
||||||
|
allRequiredInstalled &= DrawPlugin(plugin, checklistPadding);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.Spacing();
|
||||||
|
ImGui.Separator();
|
||||||
|
ImGui.Spacing();
|
||||||
|
|
||||||
|
ImGui.Text("The following plugins are recommended, but not required:");
|
||||||
|
using (ImRaii.PushIndent())
|
||||||
|
{
|
||||||
|
foreach (var plugin in RecommendedPlugins)
|
||||||
|
DrawPlugin(plugin, checklistPadding);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.Spacing();
|
||||||
|
ImGui.Separator();
|
||||||
|
ImGui.Spacing();
|
||||||
|
|
||||||
|
if (allRequiredInstalled)
|
||||||
|
{
|
||||||
|
using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.ParsedGreen))
|
||||||
|
{
|
||||||
|
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Check, "Finish Setup"))
|
||||||
|
{
|
||||||
|
_configuration.MarkPluginSetupComplete();
|
||||||
|
_pluginInterface.SavePluginConfig(_configuration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using (ImRaii.Disabled())
|
||||||
|
{
|
||||||
|
using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudRed))
|
||||||
|
ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Check, "Missing required plugins");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
|
||||||
|
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Times, "Close window & don't enable Questionable"))
|
||||||
|
{
|
||||||
|
IsOpen = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool DrawPlugin(PluginInfo plugin, float checklistPadding)
|
||||||
|
{
|
||||||
|
bool isInstalled = IsPluginInstalled(plugin.DisplayName);
|
||||||
|
using (ImRaii.PushId("plugin_" + plugin.DisplayName))
|
||||||
|
{
|
||||||
|
_uiUtils.ChecklistItem(plugin.DisplayName, isInstalled);
|
||||||
|
using (ImRaii.PushIndent(checklistPadding))
|
||||||
|
{
|
||||||
|
ImGui.TextUnformatted(plugin.Details);
|
||||||
|
if (!isInstalled && ImGui.Button("Open Repository"))
|
||||||
|
Util.OpenLink(plugin.Uri.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return isInstalled;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsPluginInstalled(string internalName)
|
||||||
|
{
|
||||||
|
return _dalamudReflector.TryGetDalamudPlugin(internalName, out _, suppressErrors: true, ignoreCache: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed record PluginInfo(
|
||||||
|
string DisplayName,
|
||||||
|
string Details,
|
||||||
|
Uri Uri);
|
||||||
|
}
|
@ -113,6 +113,9 @@ internal sealed class QuestWindow : LWindow, IPersistableWindowConfig
|
|||||||
|
|
||||||
public override bool DrawConditions()
|
public override bool DrawConditions()
|
||||||
{
|
{
|
||||||
|
if (!_configuration.IsPluginSetupComplete())
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!_clientState.IsLoggedIn || _clientState.LocalPlayer == null || _clientState.IsPvPExcludingDen)
|
if (!_clientState.IsLoggedIn || _clientState.LocalPlayer == null || _clientState.IsPvPExcludingDen)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user