Compare commits

...

No commits in common. "main" and "e17ad7fcab7ed5c6605d7fac2d8b947812077928" have entirely different histories.

8 changed files with 50 additions and 165 deletions

View File

@ -1,11 +1,10 @@
<Project>
<Target Name="PackagePlugin"
AfterTargets="Build"
Condition="'$(Configuration)' == 'Release Illegal' or '$(Configuration)' == 'Release Official'">
<DalamudPackager ProjectDir="$(ProjectDir)"
OutputPath="$(OutputPath)"
AssemblyName="$(AssemblyName)"
VersionComponents="3"
MakeZip="true" />
<Target Name="PackagePlugin" AfterTargets="Build" Condition="'$(Configuration)' == 'Release Illegal' or '$(Configuration)' == 'Release Official'">
<DalamudPackager
ProjectDir="$(ProjectDir)"
OutputPath="$(OutputPath)"
AssemblyName="$(AssemblyName)"
VersionComponents="3"
MakeZip="true"/>
</Target>
</Project>
</Project>

View File

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using Dalamud.ContextMenu;
using Dalamud.Data;
using Dalamud.Game;
using Dalamud.Game.ClientState;
@ -39,11 +38,6 @@ namespace RoleplayersToolbox {
[PluginService]
internal CommandManager CommandManager { get; init; } = null!;
// [PluginService]
// internal ContextMenu ContextMenu { get; init; } = null!;
internal DalamudContextMenu ContextMenu { get; }
[PluginService]
internal DataManager DataManager { get; init; } = null!;
@ -67,9 +61,7 @@ namespace RoleplayersToolbox {
public Plugin() {
this.Config = this.Interface.GetPluginConfig() as Configuration ?? new Configuration();
this.Common = new XivCommonBase(Hooks.PartyFinderListings);
this.ContextMenu = new DalamudContextMenu();
this.Common = new XivCommonBase(Hooks.ContextMenu | Hooks.PartyFinderListings);
this.Tools.Add(new HousingTool(this));
this.Tools.Add(new TargetingTool(this));

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5-windows</TargetFramework>
<Version>0.3.5</Version>
<Version>0.3.2</Version>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@ -26,45 +26,35 @@
<DefineConstants>TRACE;DEBUG;ILLEGAL;</DefineConstants>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<PropertyGroup>
<Dalamud>$(AppData)\XIVLauncher\addon\Hooks\dev</Dalamud>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))'">
<Dalamud>$(DALAMUD_HOME)</Dalamud>
</PropertyGroup>
<PropertyGroup Condition="'$(IsCI)' == 'true'">
<Dalamud>$(HOME)/dalamud</Dalamud>
</PropertyGroup>
<ItemGroup>
<Reference Include="Dalamud">
<HintPath>$(Dalamud)\Dalamud.dll</HintPath>
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Dalamud.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="FFXIVClientStructs">
<HintPath>$(Dalamud)\FFXIVClientStructs.dll</HintPath>
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\FFXIVClientStructs.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="ImGui.NET">
<HintPath>$(Dalamud)\ImGui.NET.dll</HintPath>
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\ImGui.NET.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="ImGuiScene">
<HintPath>$(Dalamud)\ImGuiScene.dll</HintPath>
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\ImGuiScene.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Lumina">
<HintPath>$(Dalamud)\Lumina.dll</HintPath>
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Lumina.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Lumina.Excel">
<HintPath>$(Dalamud)\Lumina.Excel.dll</HintPath>
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Lumina.Excel.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Dalamud.ContextMenu" Version="1.1.1"/>
<PackageReference Include="DalamudPackager" Version="2.1.7"/>
<PackageReference Include="F23.StringSimilarity" Version="5.0.0"/>
<PackageReference Include="XivCommon" Version="5.0.1-alpha.1"/>
<PackageReference Include="DalamudPackager" Version="2.1.4"/>
<PackageReference Include="F23.StringSimilarity" Version="4.1.0"/>
<PackageReference Include="XivCommon" Version="3.2.0"/>
</ItemGroup>
</Project>

View File

@ -1,6 +1,5 @@
name: The Roleplayer's Toolbox
author: ascclemens
punchline: "The Roleplayer's Toolbox"
description: |-
A collection of useful tools for roleplayers.
@ -12,4 +11,4 @@ description: |-
- Add the /emoteid command to use any emote by its ID.
- Disable the /doze emote snap so you can use the sleep emote
anywhere.
repo_url: https://git.annaclemens.io/ascclemens/RoleplayersToolbox
repo_url: https://git.sr.ht/~jkcclemens/RoleplayersToolbox

View File

@ -8,7 +8,6 @@ namespace RoleplayersToolbox.Tools.Housing {
LavenderBeds = 340,
Goblet = 341,
Shirogane = 641,
Empyreum = 979,
}
internal static class HousingAreaExtensions {
@ -17,7 +16,6 @@ namespace RoleplayersToolbox.Tools.Housing {
HousingArea.LavenderBeds => "Lavender Beds",
HousingArea.Goblet => "Goblet",
HousingArea.Shirogane => "Shirogane",
HousingArea.Empyreum => "Empyreum",
_ => throw new ArgumentOutOfRangeException(nameof(area), area, null),
};
@ -26,7 +24,6 @@ namespace RoleplayersToolbox.Tools.Housing {
HousingArea.LavenderBeds => 132,
HousingArea.Goblet => 130,
HousingArea.Shirogane => 628,
HousingArea.Empyreum => 418,
_ => throw new ArgumentOutOfRangeException(nameof(area), area, null),
};

View File

@ -11,12 +11,6 @@ namespace RoleplayersToolbox.Tools.Housing {
[44] = 1966110, // Lavender South Subdivision
[45] = 1966110,
},
[HousingArea.Goblet] = new() {
[4] = 1966113, // Goblet Exchange
},
[HousingArea.Mist] = new() {
[46] = 1966095, // Central Mist Subdivision
},
[HousingArea.Shirogane] = new() {
[5] = 1966135, // Southern Shirogane
},

View File

@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using Dalamud.ContextMenu;
using Dalamud.Game;
using Dalamud.Game.Command;
using Dalamud.Game.Text.SeStringHandling;
@ -12,6 +10,7 @@ using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using FFXIVClientStructs.FFXIV.Component.GUI;
using ImGuiNET;
using Lumina.Excel.GeneratedSheets;
using XivCommon.Functions.ContextMenu;
namespace RoleplayersToolbox.Tools.Housing {
internal class HousingTool : BaseTool, IDisposable {
@ -48,8 +47,6 @@ namespace RoleplayersToolbox.Tools.Housing {
private readonly AddonMapHideDelegate? _addonMapHide;
private readonly List<(string, List<World>)> _worlds = new();
internal HousingTool(Plugin plugin) {
this.Plugin = plugin;
this.Config = plugin.Config.Tools.Housing;
@ -57,20 +54,11 @@ namespace RoleplayersToolbox.Tools.Housing {
this.BookmarksUi = new BookmarksUi(plugin, this, this.Config);
this.Teleport = new Teleport(plugin);
this._worlds = this.Plugin.DataManager.GetExcelSheet<World>()!
.Where(row => row.IsPublic)
.GroupBy(row => row.DataCenter.Value!)
.Where(grouping => grouping.Key.Region != 0)
.OrderBy(grouping => grouping.Key.Region)
.ThenBy(grouping => grouping.Key.Name.RawString)
.Select(grouping => (grouping.Key.Name.RawString, grouping.OrderBy(row => row.Name.RawString).ToList()))
.ToList();
if (this.Plugin.SigScanner.TryScanText(Signatures.AddonMapHide, out var addonMapHidePtr)) {
this._addonMapHide = Marshal.GetDelegateForFunctionPointer<AddonMapHideDelegate>(addonMapHidePtr);
}
this.Plugin.ContextMenu.OnOpenGameObjectContextMenu += this.OnContextMenu;
this.Plugin.Common.Functions.ContextMenu.OpenContextMenu += this.OnContextMenu;
this.Plugin.Framework.Update += this.OnFramework;
this.Plugin.CommandManager.AddHandler("/route", new CommandInfo(this.OnRouteCommand) {
HelpMessage = "Extract housing information from the given text and open the routing window",
@ -84,7 +72,7 @@ namespace RoleplayersToolbox.Tools.Housing {
this.Plugin.CommandManager.RemoveHandler("/bookmarks");
this.Plugin.CommandManager.RemoveHandler("/route");
this.Plugin.Framework.Update -= this.OnFramework;
this.Plugin.ContextMenu.OnOpenGameObjectContextMenu -= this.OnContextMenu;
this.Plugin.Common.Functions.ContextMenu.OpenContextMenu -= this.OnContextMenu;
}
public override void DrawSettings(ref bool anyChanged) {
@ -128,34 +116,19 @@ namespace RoleplayersToolbox.Tools.Housing {
var world = this.Destination.World;
if (ImGui.BeginCombo("World", world?.Name?.ToString() ?? string.Empty)) {
var currentDc = this.Plugin.ClientState.LocalPlayer?.CurrentWorld.GameData?.DataCenter?.Value?.Name?.RawString;
var dataCentre = this.Plugin.ClientState.LocalPlayer?.HomeWorld.GameData.DataCenter?.Row;
foreach (var (dc, worlds) in this._worlds) {
if (ImGui.IsWindowAppearing() && world == null && dc == currentDc) {
ImGui.SetScrollHereY(0.5f);
foreach (var availWorld in this.Plugin.DataManager.GetExcelSheet<World>()!) {
if (availWorld.DataCenter.Row != dataCentre || !availWorld.IsPublic) {
continue;
}
ImGui.PushStyleColor(ImGuiCol.Text, ImGui.GetStyle().Colors[(int) ImGuiCol.TextDisabled]);
ImGui.TextUnformatted(dc);
ImGui.PopStyleColor();
ImGui.Separator();
foreach (var availWorld in worlds) {
var isSelected = world?.RowId == availWorld.RowId;
if (ImGui.IsWindowAppearing() && isSelected) {
ImGui.SetScrollHereY(0.5f);
}
if (!ImGui.Selectable(availWorld.Name.RawString, isSelected)) {
continue;
}
this.Destination.World = availWorld;
anyChanged = true;
if (!ImGui.Selectable(availWorld.Name.ToString())) {
continue;
}
ImGui.Spacing();
this.Destination.World = availWorld;
anyChanged = true;
}
ImGui.EndCombo();
@ -225,24 +198,19 @@ namespace RoleplayersToolbox.Tools.Housing {
this.BookmarksUi.ShouldDraw ^= true;
}
private void OnContextMenu(GameObjectContextMenuOpenArgs args) {
if (args.ParentAddonName != "LookingForGroup" || args.ContentIdLower is 0) {
private void OnContextMenu(ContextMenuOpenArgs args) {
if (args.ParentAddonName != "LookingForGroup" || args.ContentIdLower == 0) {
return;
}
args.AddCustomItem(new GameObjectContextMenuItem("Select as Destination", this.SelectDestination));
args.AddCustomItem(new GameObjectContextMenuItem("Add Bookmark", this.AddBookmark));
args.Items.Add(new NormalContextSubMenuItem("Roleplayer's Toolbox", args => {
args.Items.Add(new NormalContextMenuItem("Select as Destination", this.SelectDestination));
args.Items.Add(new NormalContextMenuItem("Add Bookmark", this.AddBookmark));
}));
}
private void SelectDestination(GameObjectContextMenuItemSelectedArgs args) {
var contentId = args.ContentIdLower;
if (contentId is 0) {
return;
}
var contentIdLower = contentId & 0xFFFFFFFF;
var listing = this.Plugin.Common.Functions.PartyFinder.CurrentListings.Values.FirstOrDefault(listing => listing.ContentIdLower == contentIdLower);
private void SelectDestination(ContextMenuItemSelectedArgs args) {
var listing = this.Plugin.Common.Functions.PartyFinder.CurrentListings.Values.FirstOrDefault(listing => listing.ContentIdLower == args.ContentIdLower);
if (listing == null) {
return;
}
@ -251,15 +219,8 @@ namespace RoleplayersToolbox.Tools.Housing {
this.Destination = InfoExtractor.Extract(listing.Description.TextValue, listing.World.Value.DataCenter.Row, this.Plugin.DataManager, this.Info);
}
private void AddBookmark(GameObjectContextMenuItemSelectedArgs args) {
var contentId = args.ContentIdLower;
if (contentId is 0) {
return;
}
var contentIdLower = contentId & 0xFFFFFFFF;
var listing = this.Plugin.Common.Functions.PartyFinder.CurrentListings.Values.FirstOrDefault(listing => listing.ContentIdLower == contentIdLower);
private void AddBookmark(ContextMenuItemSelectedArgs args) {
var listing = this.Plugin.Common.Functions.PartyFinder.CurrentListings.Values.FirstOrDefault(listing => listing.ContentIdLower == args.ContentIdLower);
if (listing == null) {
return;
}
@ -279,7 +240,6 @@ namespace RoleplayersToolbox.Tools.Housing {
this.HighlightSelectString();
this.HighlightResidentialTeleport();
this.HighlightWorldTravel();
this.HighlightTeleportTown();
}
private void ClearIfNear() {
@ -337,7 +297,7 @@ namespace RoleplayersToolbox.Tools.Housing {
}
private unsafe void ClearFlag() {
var mapAgent = (IntPtr) FFXIVClientStructs.FFXIV.Client.System.Framework.Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.Map);
var mapAgent = (IntPtr) this.Plugin.Common.Functions.GetFramework()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.Map);
if (mapAgent != IntPtr.Zero) {
*(byte*) (mapAgent + AgentMapFlagSetOffset) = 0;
}
@ -440,7 +400,7 @@ namespace RoleplayersToolbox.Tools.Housing {
}
var select = (AddonSelectString*) addon;
var list = select->PopupMenu.PopupMenu.List;
var list = select->PopupMenu.List;
if (list == null) {
return;
}
@ -456,6 +416,13 @@ namespace RoleplayersToolbox.Tools.Housing {
return text == " Visit Another World Server.";
}
// TODO: figure out how to use HousingAethernet.Order with current one missing
var placeName = this.Destination?.ClosestAethernet?.PlaceName?.Value?.Name?.ToString();
var currentWard = this.Plugin.Common.Functions.Housing.Location?.Ward;
if (currentWard == this.Destination?.Ward && placeName != null && text.StartsWith(placeName) && text.Length == placeName.Length + 1) {
return true;
}
// ReSharper disable once InvertIf
if (this.Destination?.Ward != null && this.Plugin.ClientState.TerritoryType == this.Destination?.Area?.CityStateTerritoryType()) {
switch (text) {
@ -480,54 +447,6 @@ namespace RoleplayersToolbox.Tools.Housing {
}
}
private unsafe void HighlightTeleportTown() {
var player = this.Plugin.ClientState.LocalPlayer;
if (player == null) {
return;
}
var world = this.Destination?.World;
if (world?.RowId != player.CurrentWorld.Id) {
return;
}
var addon = this.Plugin.GameGui.GetAddonByName("TelepotTown", 1);
if (addon == IntPtr.Zero) {
return;
}
var unit = (AtkUnitBase*) addon;
var root = unit->RootNode;
if (root == null) {
return;
}
var windowNode = root->ChildNode;
var list = windowNode->PrevSiblingNode->PrevSiblingNode;
var treeNode = (AtkComponentNode*) list->ChildNode;
var collisionNode = treeNode->Component->UldManager.RootNode;
var child = collisionNode->PrevSiblingNode;
while (child != null) {
var component = (AtkComponentNode*) child;
if (child->Type != (NodeType) 1020 || component->Component->UldManager.NodeListSize != 7) {
goto End;
}
var childCollisionNode = component->Component->UldManager.RootNode;
var textNode = (AtkTextNode*) childCollisionNode->PrevSiblingNode->PrevSiblingNode->PrevSiblingNode;
var text = textNode->NodeText.ToString();
var placeName = this.Destination?.ClosestAethernet?.PlaceName?.Value?.Name?.ToString();
var currentWard = this.Plugin.Common.Functions.Housing.Location?.Ward;
HighlightIf(&textNode->AtkResNode, currentWard == this.Destination?.Ward && placeName != null && text == placeName);
End:
child = child->PrevSiblingNode;
}
}
private unsafe void HighlightWorldTravel() {
var player = this.Plugin.ClientState.LocalPlayer;
if (player == null) {

View File

@ -27,11 +27,6 @@ namespace RoleplayersToolbox.Tools.Housing {
new Regex(@"\bshirogane\b", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"\bshiro\b", RegexOptions.Compiled | RegexOptions.IgnoreCase),
},
[HousingArea.Empyreum] = new[] {
new Regex(@"\bemp[ye]r[ie]um\b", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"\bempy\b", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"\bemp\b", RegexOptions.Compiled | RegexOptions.IgnoreCase),
},
};
private static readonly JaroWinkler JaroWinkler = new();