diff --git a/README.md b/README.md index 1ca0a33..76ef07e 100644 --- a/README.md +++ b/README.md @@ -1,47 +1,13 @@ -# SamplePlugin +# SneakOnBy -Simple example plugin for Dalamud. +Paints the aggression zones around monsters in Deep Dungeons. Supports proximity, sound, and sight based monsters. -This is not designed to be the simplest possible example, but it is also not designed to cover everything you might want to do. For more detailed questions, come ask in [the Discord](https://discord.gg/3NMcUV5). +Requires [DeepDungeonDex](https://github.com/wolfcomp/DeepDungeonDex) to be installed as well. -## Main Points +## Usage -* Simple functional plugin - * Slash command - * Main UI - * Settings UI - * Image loading - * Plugin json -* Simple, slightly-improved plugin configuration handling -* Project organization - * Copies all necessary plugin files to the output directory - * Does not copy dependencies that are provided by dalamud - * Output directory can be zipped directly and have exactly what is required - * Hides data files from visual studio to reduce clutter - * Also allows having data files in different paths than VS would usually allow if done in the IDE directly +Install with custom repo (coming soon). +Use command `/sneaky` to configure options. -The intention is less that any of this is used directly in other projects, and more to show how similar things can be done. - -## To Use -### Building - -1. Open up `SamplePlugin.sln` in your C# editor of choice (likely [Visual Studio 2022](https://visualstudio.microsoft.com) or [JetBrains Rider](https://www.jetbrains.com/rider/)). -2. Build the solution. By default, this will build a `Debug` build, but you can switch to `Release` in your IDE. -3. The resulting plugin can be found at `SamplePlugin/bin/x64/Debug/SamplePlugin.dll` (or `Release` if appropriate.) - -### Activating in-game - -1. Launch the game and use `/xlsettings` in chat or `xlsettings` in the Dalamud Console to open up the Dalamud settings. - * In here, go to `Experimental`, and add the full path to the `SamplePlugin.dll` to the list of Dev Plugin Locations. -2. Next, use `/xlplugins` (chat) or `xlplugins` (console) to open up the Plugin Installer. - * In here, go to `Dev Tools > Installed Dev Plugins`, and the `SamplePlugin` should be visible. Enable it. -3. You should now be able to use `/pmycommand` (chat) or `pmycommand` (console)! - -Note that you only need to add it to the Dev Plugin Locations once (Step 1); it is preserved afterwards. You can disable, enable, or load your plugin on startup through the Plugin Installer. - -### Reconfiguring for your own uses - -Basically, just replace all references to `SamplePlugin` in all of the files and filenames with your desired name. You'll figure it out 😁 - -Dalamud will load the JSON file (by default, `SamplePlugin/SamplePlugin.json`) next to your DLL and use it for metadata, including the description for your plugin in the Plugin Installer. Make sure to update this with information relevant to _your_ plugin! \ No newline at end of file +Still a work in progress. \ No newline at end of file diff --git a/SneakOnBy/Configuration.cs b/SneakOnBy/Configuration.cs index aad84a0..3bd2dbe 100644 --- a/SneakOnBy/Configuration.cs +++ b/SneakOnBy/Configuration.cs @@ -10,6 +10,8 @@ public class Configuration : IPluginConfiguration public int Version { get; set; } = 0; public bool EnableLineOfSight { get; set; } = true; + public bool EnableProximity { get; set; } = true; + public bool EnableSound { get; set; } = true; // the below exist just to make saving less cumbersome [NonSerialized] diff --git a/SneakOnBy/DeepDungeonDex.cs b/SneakOnBy/DeepDungeonDex.cs index a5cd2fc..67caee1 100644 --- a/SneakOnBy/DeepDungeonDex.cs +++ b/SneakOnBy/DeepDungeonDex.cs @@ -21,10 +21,14 @@ internal static class DeepDungeonDex internal static IDalamudPlugin Instance; internal static object StorageHandler; - internal static void Init() + internal static Boolean TryConnect() { - Connect(); - DalamudReflector.RegisterOnInstalledPluginsChangedEvents(Connect); + if (Instance == null || StorageHandler == null) + { + Connect(); + } + + return Instance != null && StorageHandler != null; } static void Connect() @@ -72,7 +76,7 @@ internal static void Reset() public static Aggro GetMobAggroType(uint id) { - if(StorageHandler != null) + if(TryConnect()) { Type mobDataType = Assembly.GetAssembly(StorageHandler.GetType()).GetType("DeepDungeonDex.Storage.MobData"); MethodInfo getInstancesMethod = StorageHandler.GetType().GetMethod("GetInstances", new Type[] { }).MakeGenericMethod(new Type[] { mobDataType }); diff --git a/SneakOnBy/Plugin.cs b/SneakOnBy/Plugin.cs index aec54cf..4bb0a42 100644 --- a/SneakOnBy/Plugin.cs +++ b/SneakOnBy/Plugin.cs @@ -37,7 +37,7 @@ public Plugin( this.CommandManager = commandManager; ECommonsMain.Init(pluginInterface, this, Module.DalamudReflector, Module.ObjectFunctions); - DeepDungeonDex.Init(); + DeepDungeonDex.TryConnect(); this.Configuration = this.PluginInterface.GetPluginConfig() as Configuration ?? new Configuration(); this.Configuration.Initialize(this.PluginInterface); @@ -62,6 +62,7 @@ public Plugin( this.PluginInterface.UiBuilder.Draw += DrawUI; this.PluginInterface.UiBuilder.OpenConfigUi += DrawConfigUI; Svc.Condition.ConditionChange += ConditionChange; + } public void Dispose() diff --git a/SneakOnBy/Windows/Canvas.cs b/SneakOnBy/Windows/Canvas.cs index 4ed536c..0f0e406 100644 --- a/SneakOnBy/Windows/Canvas.cs +++ b/SneakOnBy/Windows/Canvas.cs @@ -2,24 +2,15 @@ using System.Numerics; using Dalamud.Interface.Windowing; using ImGuiNET; -using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Game.ClientState.Objects.Types; -using Dalamud.Interface.GameFonts; -using Dalamud.Game.ClientState; using ECommons.GameFunctions; using ECommons.DalamudServices; using Dalamud.Interface; using ECommons.MathHelpers; -using FFXIVClientStructs.FFXIV.Client.Game.Control; -using FFXIVClientStructs.FFXIV.Component.GUI; -using Dalamud.Logging; -using System.Buffers.Text; -using FFXIVClientStructs.FFXIV.Client.System.Framework; -using FFXIVClientStructs.FFXIV.Client.UI; -using FFXIVClientStructs.FFXIV.Client.Game.Character; using Dalamud.Game.ClientState.Objects.Enums; using Dalamud.Interface.Colors; using Dalamud.Utility.Numerics; +using Dalamud.Game.ClientState.Conditions; namespace SneakOnBy.Windows; @@ -53,31 +44,37 @@ public override void PreDraw() public override bool DrawConditions() { - return Svc.ClientState.LocalPlayer != null; + return Svc.ClientState.LocalPlayer != null && Svc.Condition[ConditionFlag.InDeepDungeon]; } public void Dispose() { } public override void Draw() { - if (this.configuration.EnableLineOfSight) + foreach (GameObject obj in Svc.Objects) { - foreach (GameObject obj in Svc.Objects) - { - if (obj is BattleNpc bnpc && bnpc.IsHostile() && !bnpc.StatusFlags.HasFlag(StatusFlags.InCombat) && bnpc.IsCharacterVisible()) { - Aggro aggro = DeepDungeonDex.GetMobAggroType(bnpc.NameId); - switch (aggro) - { - case Aggro.Sight: + if (obj is BattleNpc bnpc && bnpc.IsHostile() && !bnpc.StatusFlags.HasFlag(StatusFlags.InCombat) && bnpc.IsCharacterVisible()) { + Aggro aggro = DeepDungeonDex.GetMobAggroType(bnpc.NameId); + switch (aggro) + { + case Aggro.Sight: + if (this.configuration.EnableLineOfSight) + { ActorConeXZ(bnpc, bnpc.HitboxRadius + 10, Radians(-45), Radians(45), ImGuiColors.DalamudRed.WithW(0.2f)); - break; - case Aggro.Proximity: + } + break; + case Aggro.Proximity: + if (this.configuration.EnableProximity) + { CircleArcXZ(bnpc.Position, bnpc.HitboxRadius + 10, 0f, TAU, ImGuiColors.DalamudRed.WithW(0.2f)); - break; - case Aggro.Sound: + } + break; + case Aggro.Sound: + if (this.configuration.EnableSound) + { CircleArcXZ(bnpc.Position, bnpc.HitboxRadius + 10, 0f, TAU, ImGuiColors.DalamudOrange.WithW(0.2f)); - break; - } + } + break; } } } diff --git a/SneakOnBy/Windows/ConfigWindow.cs b/SneakOnBy/Windows/ConfigWindow.cs index 062e37e..5ac256d 100644 --- a/SneakOnBy/Windows/ConfigWindow.cs +++ b/SneakOnBy/Windows/ConfigWindow.cs @@ -14,7 +14,7 @@ public ConfigWindow(Plugin plugin) : base( ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse) { - this.Size = new Vector2(232, 75); + this.Size = new Vector2(232, 100); this.SizeCondition = ImGuiCond.Always; this.configuration = plugin.Configuration; @@ -25,10 +25,26 @@ public void Dispose() { } public override void Draw() { // can't ref a property, so use a local copy - var configValue = this.configuration.EnableLineOfSight; - if (ImGui.Checkbox("Enable Line of Sight Telegraph", ref configValue)) + var losConfigValue = this.configuration.EnableLineOfSight; + if (ImGui.Checkbox("Enable Line of Sight Zones", ref losConfigValue)) { - this.configuration.EnableLineOfSight = configValue; + this.configuration.EnableLineOfSight = losConfigValue; + // can save immediately on change, if you don't want to provide a "Save and Close" button + this.configuration.Save(); + } + + var proxConfigValue = this.configuration.EnableProximity; + if (ImGui.Checkbox("Enable Proximity Zones", ref proxConfigValue)) + { + this.configuration.EnableProximity = proxConfigValue; + // can save immediately on change, if you don't want to provide a "Save and Close" button + this.configuration.Save(); + } + + var soundConfigValue = this.configuration.EnableSound; + if (ImGui.Checkbox("Enable Sound Zones", ref soundConfigValue)) + { + this.configuration.EnableSound = soundConfigValue; // can save immediately on change, if you don't want to provide a "Save and Close" button this.configuration.Save(); }