2ed125d520
Adds ExtraChat Linkshell channels to tab input channel selector. These are only by index, not by channel name due to limitations in the ExtraChat IPC API. Adds ExtraChat Linkshell channels to the channel selector in the chat log window. As these aren't real channels in-game, these are handled by just sending the corresponding `/eclX` command which causes ExtraChat to set a channel override.
629 lines
22 KiB
C#
Executable File
629 lines
22 KiB
C#
Executable File
using System.Numerics;
|
|
using ChatTwo.Code;
|
|
using ChatTwo.Resources;
|
|
using ChatTwo.Ui;
|
|
using ChatTwo.Util;
|
|
using Dalamud.Game.Addon.Lifecycle;
|
|
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
|
|
using Dalamud.Game.ClientState.Objects.SubKinds;
|
|
using Dalamud.Game.Config;
|
|
using Dalamud.Game.Text.SeStringHandling;
|
|
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
|
using Dalamud.Interface.Internal;
|
|
using Dalamud.Interface.Internal.Notifications;
|
|
using Dalamud.Interface.Utility;
|
|
using Dalamud.Utility;
|
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
|
using ImGuiNET;
|
|
using Lumina.Excel;
|
|
using Lumina.Excel.GeneratedSheets;
|
|
|
|
using Action = System.Action;
|
|
using DalamudPartyFinderPayload = Dalamud.Game.Text.SeStringHandling.Payloads.PartyFinderPayload;
|
|
using ChatTwoPartyFinderPayload = ChatTwo.Util.PartyFinderPayload;
|
|
|
|
namespace ChatTwo;
|
|
|
|
public sealed class PayloadHandler {
|
|
private const string PopupId = "chat2-context-popup";
|
|
|
|
private ChatLogWindow LogWindow { get; }
|
|
private (Chunk, Payload?)? Popup { get; set; }
|
|
|
|
private bool _handleTooltips;
|
|
private uint _hoveredItem;
|
|
private uint _hoverCounter;
|
|
private uint _lastHoverCounter;
|
|
|
|
private readonly ExcelSheet<Item> ItemSheet;
|
|
private readonly ExcelSheet<EventItem> EventItemSheet;
|
|
private readonly ExcelSheet<TerritoryType> TerritorySheet;
|
|
private readonly ExcelSheet<EventItemHelp> EventItemHelpSheet;
|
|
|
|
internal PayloadHandler(ChatLogWindow logWindow) {
|
|
LogWindow = logWindow;
|
|
|
|
ItemSheet = Plugin.DataManager.GetExcelSheet<Item>()!;
|
|
EventItemSheet = Plugin.DataManager.GetExcelSheet<EventItem>()!;
|
|
TerritorySheet = Plugin.DataManager.GetExcelSheet<TerritoryType>()!;
|
|
EventItemHelpSheet = Plugin.DataManager.GetExcelSheet<EventItemHelp>()!;
|
|
}
|
|
|
|
internal void Draw() {
|
|
DrawPopups();
|
|
|
|
if (_handleTooltips && ++_hoverCounter - _lastHoverCounter > 1) {
|
|
GameFunctions.GameFunctions.CloseItemTooltip();
|
|
_hoveredItem = 0;
|
|
_hoverCounter = _lastHoverCounter = 0;
|
|
_handleTooltips = false;
|
|
}
|
|
}
|
|
|
|
private void DrawPopups() {
|
|
if (Popup == null) {
|
|
return;
|
|
}
|
|
|
|
var (chunk, payload) = Popup.Value;
|
|
|
|
if (!ImGui.BeginPopup(PopupId)) {
|
|
Popup = null;
|
|
return;
|
|
}
|
|
|
|
ImGui.PushID(PopupId);
|
|
|
|
var drawn = false;
|
|
switch (payload) {
|
|
case PlayerPayload player: {
|
|
DrawPlayerPopup(chunk, player);
|
|
drawn = true;
|
|
break;
|
|
}
|
|
case ItemPayload item: {
|
|
DrawItemPopup(item);
|
|
drawn = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ContextFooter(drawn, chunk);
|
|
Integrations(chunk, payload);
|
|
|
|
ImGui.PopID();
|
|
ImGui.EndPopup();
|
|
}
|
|
|
|
private void Integrations(Chunk chunk, Payload? payload) {
|
|
var registered = LogWindow.Plugin.Ipc.Registered;
|
|
if (registered.Count == 0) {
|
|
return;
|
|
}
|
|
|
|
var contentId = chunk.Message?.ContentId ?? 0;
|
|
var sender = chunk.Message?.Sender
|
|
.Select(chunk => chunk.Link)
|
|
.FirstOrDefault(chunk => chunk is PlayerPayload) as PlayerPayload;
|
|
|
|
if (ImGui.BeginMenu(Language.Context_Integrations)) {
|
|
var cursor = ImGui.GetCursorPos();
|
|
|
|
foreach (var id in registered) {
|
|
try {
|
|
LogWindow.Plugin.Ipc.Invoke(id, sender, contentId, payload, chunk.Message?.SenderSource, chunk.Message?.ContentSource);
|
|
} catch (Exception ex) {
|
|
Plugin.Log.Error(ex, "Error executing integration");
|
|
}
|
|
}
|
|
|
|
if (cursor == ImGui.GetCursorPos()) {
|
|
ImGui.PushStyleColor(ImGuiCol.Text, ImGui.GetStyle().Colors[(int) ImGuiCol.TextDisabled]);
|
|
ImGui.Text("No integrations available");
|
|
ImGui.PopStyleColor();
|
|
}
|
|
|
|
ImGui.EndMenu();
|
|
}
|
|
}
|
|
|
|
private void ContextFooter(bool separator, Chunk chunk) {
|
|
if (separator) {
|
|
ImGui.Separator();
|
|
}
|
|
|
|
if (!ImGui.BeginMenu(Plugin.PluginName)) {
|
|
return;
|
|
}
|
|
|
|
ImGui.Checkbox(Language.Context_ScreenshotMode, ref LogWindow.ScreenshotMode);
|
|
|
|
if (ImGui.Selectable(Language.Context_HideChat)) {
|
|
LogWindow.UserHide();
|
|
}
|
|
|
|
if (chunk.Message is { } message) {
|
|
if (ImGui.BeginMenu(Language.Context_Copy)) {
|
|
var text = message.Sender
|
|
.Concat(message.Content)
|
|
.Where(chunk => chunk is TextChunk)
|
|
.Cast<TextChunk>()
|
|
.Select(text => text.Content)
|
|
.Aggregate(string.Concat);
|
|
ImGui.InputTextMultiline(
|
|
"##chat2-copy",
|
|
ref text,
|
|
(uint) text.Length,
|
|
new Vector2(350, 100) * ImGuiHelpers.GlobalScale,
|
|
ImGuiInputTextFlags.ReadOnly
|
|
);
|
|
ImGui.EndMenu();
|
|
}
|
|
|
|
var col = ImGui.GetStyle().Colors[(int) ImGuiCol.TextDisabled];
|
|
ImGui.PushStyleColor(ImGuiCol.Text, col);
|
|
try
|
|
{
|
|
ImGui.TextUnformatted(message.Code.Type.Name());
|
|
}
|
|
finally
|
|
{
|
|
ImGui.PopStyleColor();
|
|
}
|
|
}
|
|
|
|
ImGui.EndMenu();
|
|
}
|
|
|
|
internal void Click(Chunk chunk, Payload? payload, ImGuiMouseButton button) {
|
|
switch (button) {
|
|
case ImGuiMouseButton.Left:
|
|
LeftClickPayload(chunk, payload);
|
|
break;
|
|
case ImGuiMouseButton.Right:
|
|
RightClickPayload(chunk, payload);
|
|
break;
|
|
}
|
|
}
|
|
|
|
internal void Hover(Payload payload) {
|
|
var hoverSize = 250f * ImGuiHelpers.GlobalScale;
|
|
|
|
switch (payload) {
|
|
case StatusPayload status: {
|
|
DoHover(() => HoverStatus(status), hoverSize);
|
|
break;
|
|
}
|
|
case ItemPayload item: {
|
|
if (LogWindow.Plugin.Config.NativeItemTooltips) {
|
|
GameFunctions.GameFunctions.OpenItemTooltip(item.RawItemId);
|
|
|
|
_handleTooltips = true;
|
|
if (_hoveredItem != item.RawItemId)
|
|
{
|
|
_hoveredItem = item.RawItemId;
|
|
_hoverCounter = _lastHoverCounter = 0;
|
|
}
|
|
else
|
|
{
|
|
_lastHoverCounter = _hoverCounter;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
DoHover(() => HoverItem(item), hoverSize);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DoHover(Action inside, float width) {
|
|
ImGui.SetNextWindowSize(new Vector2(width, -1f));
|
|
|
|
ImGui.BeginTooltip();
|
|
ImGui.PushTextWrapPos();
|
|
ImGui.PushStyleColor(ImGuiCol.Text, LogWindow.DefaultText);
|
|
|
|
try
|
|
{
|
|
inside();
|
|
}
|
|
finally
|
|
{
|
|
ImGui.PopStyleColor();
|
|
ImGui.PopTextWrapPos();
|
|
ImGui.EndTooltip();
|
|
}
|
|
}
|
|
|
|
public unsafe void MoveTooltip(AddonEvent type, AddonArgs args)
|
|
{
|
|
if (!_handleTooltips)
|
|
return;
|
|
|
|
// Only move if user has "Next to Cursor" option selected
|
|
if (!Plugin.GameConfig.TryGet(UiControlOption.DetailTrackingType, out uint selected) || selected != 0)
|
|
return;
|
|
|
|
if (LogWindow.LastViewport != ImGuiHelpers.MainViewport.NativePtr)
|
|
return;
|
|
|
|
var atk = (AtkUnitBase*) args.Addon;
|
|
if (atk->WindowNode == null)
|
|
return;
|
|
|
|
var component = atk->WindowNode->AtkResNode;
|
|
|
|
var atkSize = (X: component.GetWidth() * component.ScaleX, Y: component.GetHeight() * component.GetScaleY());
|
|
var viewportSize = ImGuiHelpers.MainViewport.Size;
|
|
var window = LogWindow.LastWindowPos + LogWindow.LastWindowSize;
|
|
var isLeft = window.X < viewportSize.X / 2;
|
|
var isTop = window.Y < viewportSize.Y / 2;
|
|
|
|
var x = isLeft ? window.X : LogWindow.LastWindowPos.X - atkSize.X;
|
|
var y = Math.Clamp(window.Y - atkSize.Y, 0, float.MaxValue);
|
|
y -= isTop ? 0 : LogWindow.Plugin.Config.TooltipOffset; // offset to prevent cut-off on the bottom
|
|
|
|
atk->SetPosition((short) x, (short) y);
|
|
}
|
|
|
|
private static void InlineIcon(IDalamudTextureWrap icon) {
|
|
var lineHeight = ImGui.CalcTextSize("A").Y;
|
|
|
|
var cursor = ImGui.GetCursorPos();
|
|
var size = new Vector2(icon.Width, icon.Height) * ImGuiHelpers.GlobalScale;
|
|
ImGui.Image(icon.ImGuiHandle, size);
|
|
ImGui.SameLine();
|
|
ImGui.SetCursorPos(cursor + new Vector2(size.X + 4, size.Y / 2 - lineHeight / 2));
|
|
}
|
|
|
|
private void HoverStatus(StatusPayload status) {
|
|
if (LogWindow.Plugin.TextureCache.GetStatus(status.Status) is { } icon) {
|
|
InlineIcon(icon);
|
|
}
|
|
|
|
var name = ChunkUtil.ToChunks(status.Status.Name.ToDalamudString(), ChunkSource.None, null);
|
|
LogWindow.DrawChunks(name.ToList());
|
|
ImGui.Separator();
|
|
|
|
var desc = ChunkUtil.ToChunks(status.Status.Description.ToDalamudString(), ChunkSource.None, null);
|
|
LogWindow.DrawChunks(desc.ToList());
|
|
}
|
|
|
|
private void HoverItem(ItemPayload item) {
|
|
if (item.Kind == ItemPayload.ItemKind.EventItem) {
|
|
HoverEventItem(item);
|
|
return;
|
|
}
|
|
|
|
if (item.Item == null) {
|
|
return;
|
|
}
|
|
|
|
if (LogWindow.Plugin.TextureCache.GetItem(item.Item, item.IsHQ) is { } icon) {
|
|
InlineIcon(icon);
|
|
}
|
|
|
|
var name = ChunkUtil.ToChunks(item.Item.Name.ToDalamudString(), ChunkSource.None, null);
|
|
LogWindow.DrawChunks(name.ToList());
|
|
ImGui.Separator();
|
|
|
|
var desc = ChunkUtil.ToChunks(item.Item.Description.ToDalamudString(), ChunkSource.None, null);
|
|
LogWindow.DrawChunks(desc.ToList());
|
|
}
|
|
|
|
private void HoverEventItem(ItemPayload payload) {
|
|
var item = EventItemSheet.GetRow(payload.RawItemId);
|
|
if (item == null) {
|
|
return;
|
|
}
|
|
|
|
if (LogWindow.Plugin.TextureCache.GetEventItem(item) is { } icon) {
|
|
InlineIcon(icon);
|
|
}
|
|
|
|
var name = ChunkUtil.ToChunks(item.Name.ToDalamudString(), ChunkSource.None, null);
|
|
LogWindow.DrawChunks(name.ToList());
|
|
ImGui.Separator();
|
|
|
|
var help = EventItemHelpSheet.GetRow(payload.RawItemId);
|
|
if (help != null) {
|
|
var desc = ChunkUtil.ToChunks(help.Description.ToDalamudString(), ChunkSource.None, null);
|
|
LogWindow.DrawChunks(desc.ToList());
|
|
}
|
|
}
|
|
|
|
private void LeftClickPayload(Chunk chunk, Payload? payload) {
|
|
switch (payload) {
|
|
case MapLinkPayload map: {
|
|
Plugin.GameGui.OpenMapWithMapLink(map);
|
|
break;
|
|
}
|
|
case QuestPayload quest: {
|
|
LogWindow.Plugin.Common.Functions.Journal.OpenQuest(quest.Quest);
|
|
break;
|
|
}
|
|
case DalamudLinkPayload link: {
|
|
ClickLinkPayload(chunk, payload, link);
|
|
break;
|
|
}
|
|
case DalamudPartyFinderPayload pf: {
|
|
if (pf.LinkType == DalamudPartyFinderPayload.PartyFinderLinkType.PartyFinderNotification) {
|
|
GameFunctions.GameFunctions.OpenPartyFinder();
|
|
} else {
|
|
LogWindow.Plugin.Functions.OpenPartyFinder(pf.ListingId);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case ChatTwoPartyFinderPayload pf: {
|
|
LogWindow.Plugin.Functions.OpenPartyFinder(pf.Id);
|
|
break;
|
|
}
|
|
case AchievementPayload achievement: {
|
|
LogWindow.Plugin.Functions.OpenAchievement(achievement.Id);
|
|
break;
|
|
}
|
|
case RawPayload raw: {
|
|
if (Equals(raw, ChunkUtil.PeriodicRecruitmentLink)) {
|
|
GameFunctions.GameFunctions.OpenPartyFinder();
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ClickLinkPayload(Chunk chunk, Payload payload, DalamudLinkPayload link) {
|
|
if (chunk.GetSeString() is not { } source) {
|
|
return;
|
|
}
|
|
|
|
var start = source.Payloads.IndexOf(payload);
|
|
var end = source.Payloads.IndexOf(RawPayload.LinkTerminator, start == -1 ? 0 : start);
|
|
if (start == -1 || end == -1) {
|
|
return;
|
|
}
|
|
|
|
var payloads = source.Payloads.Skip(start).Take(end - start + 1).ToList();
|
|
if (!Plugin.ChatGui.RegisteredLinkHandlers.TryGetValue((link.Plugin, link.CommandId), out var value))
|
|
{
|
|
Plugin.Log.Warning("Could not find DalamudLinkHandlers");
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
// Running XivCommon SendChat instantly leads to a game freeze, for whatever reason
|
|
Plugin.Framework.RunOnTick(() => value.Invoke(link.CommandId, new SeString(payloads)));
|
|
} catch (Exception ex) {
|
|
Plugin.Log.Error(ex, "Error executing DalamudLinkPayload handler");
|
|
}
|
|
}
|
|
|
|
private void RightClickPayload(Chunk chunk, Payload? payload) {
|
|
Popup = (chunk, payload);
|
|
ImGui.OpenPopup(PopupId);
|
|
}
|
|
|
|
private void DrawItemPopup(ItemPayload payload) {
|
|
if (payload.Kind == ItemPayload.ItemKind.EventItem) {
|
|
DrawEventItemPopup(payload);
|
|
return;
|
|
}
|
|
|
|
var item = ItemSheet.GetRow(payload.ItemId);
|
|
if (item == null) {
|
|
return;
|
|
}
|
|
|
|
var hq = payload.Kind == ItemPayload.ItemKind.Hq;
|
|
|
|
if (LogWindow.Plugin.TextureCache.GetItem(item, hq) is { } icon) {
|
|
InlineIcon(icon);
|
|
}
|
|
|
|
var name = item.Name.ToDalamudString();
|
|
if (hq) {
|
|
// hq symbol
|
|
name.Payloads.Add(new TextPayload(" "));
|
|
} else if (payload.Kind == ItemPayload.ItemKind.Collectible) {
|
|
name.Payloads.Add(new TextPayload(" "));
|
|
}
|
|
|
|
LogWindow.DrawChunks(ChunkUtil.ToChunks(name, ChunkSource.None, null).ToList(), false);
|
|
ImGui.Separator();
|
|
|
|
var realItemId = payload.RawItemId;
|
|
if (item.EquipSlotCategory.Row != 0) {
|
|
if (ImGui.Selectable(Language.Context_TryOn)) {
|
|
LogWindow.Plugin.Functions.Context.TryOn(realItemId, 0);
|
|
}
|
|
|
|
if (ImGui.Selectable(Language.Context_ItemComparison)) {
|
|
LogWindow.Plugin.Functions.Context.OpenItemComparison(realItemId);
|
|
}
|
|
}
|
|
|
|
if (item.ItemSearchCategory.Value?.Category == 3) {
|
|
if (ImGui.Selectable(Language.Context_SearchRecipes)) {
|
|
LogWindow.Plugin.Functions.Context.SearchForRecipesUsingItem(payload.ItemId);
|
|
}
|
|
}
|
|
|
|
if (ImGui.Selectable(Language.Context_SearchForItem)) {
|
|
LogWindow.Plugin.Functions.Context.SearchForItem(realItemId);
|
|
}
|
|
|
|
if (ImGui.Selectable(Language.Context_Link)) {
|
|
LogWindow.Plugin.Functions.Context.LinkItem(realItemId);
|
|
}
|
|
|
|
if (ImGui.Selectable(Language.Context_CopyItemName)) {
|
|
ImGui.SetClipboardText(name.TextValue);
|
|
}
|
|
}
|
|
|
|
private void DrawEventItemPopup(ItemPayload payload) {
|
|
if (payload.Kind != ItemPayload.ItemKind.EventItem) {
|
|
return;
|
|
}
|
|
|
|
var item = EventItemSheet.GetRow(payload.ItemId);
|
|
if (item == null) {
|
|
return;
|
|
}
|
|
|
|
if (LogWindow.Plugin.TextureCache.GetEventItem(item) is { } icon) {
|
|
InlineIcon(icon);
|
|
}
|
|
|
|
var name = item.Name.ToDalamudString();
|
|
LogWindow.DrawChunks(ChunkUtil.ToChunks(name, ChunkSource.None, null).ToList(), false);
|
|
ImGui.Separator();
|
|
|
|
var realItemId = payload.RawItemId;
|
|
if (ImGui.Selectable(Language.Context_Link)) {
|
|
LogWindow.Plugin.Functions.Context.LinkItem(realItemId);
|
|
}
|
|
|
|
if (ImGui.Selectable(Language.Context_CopyItemName)) {
|
|
ImGui.SetClipboardText(name.TextValue);
|
|
}
|
|
}
|
|
|
|
private void DrawPlayerPopup(Chunk chunk, PlayerPayload player)
|
|
{
|
|
// Possible that GMs return a null payload
|
|
if (player == null)
|
|
return;
|
|
|
|
var world = player.World;
|
|
if (chunk.Message?.Code.Type == ChatType.FreeCompanyLoginLogout) {
|
|
if (Plugin.ClientState.LocalPlayer?.HomeWorld.GameData is { } homeWorld) {
|
|
world = homeWorld;
|
|
}
|
|
}
|
|
|
|
var name = new List<Chunk> { new TextChunk(ChunkSource.None, null, player.PlayerName) };
|
|
if (world.IsPublic) {
|
|
name.AddRange(new Chunk[] {
|
|
new IconChunk(ChunkSource.None, null, BitmapFontIcon.CrossWorld),
|
|
new TextChunk(ChunkSource.None, null, world.Name),
|
|
});
|
|
}
|
|
|
|
LogWindow.DrawChunks(name, false);
|
|
ImGui.Separator();
|
|
|
|
var validContentId = chunk.Message?.ContentId is not (null or 0);
|
|
if (ImGui.Selectable(Language.Context_SendTell))
|
|
{
|
|
// Eureka and Bozja need special handling as tells work different
|
|
if (TerritorySheet.GetRow(Plugin.ClientState.TerritoryType)?.TerritoryIntendedUse != 41)
|
|
{
|
|
LogWindow.Chat = $"/tell {player.PlayerName}";
|
|
if (world.IsPublic) {
|
|
LogWindow.Chat += $"@{world.Name}";
|
|
}
|
|
|
|
LogWindow.Chat += " ";
|
|
}
|
|
else if (validContentId)
|
|
{
|
|
LogWindow.Plugin.Functions.Chat.SetEurekaTellChannel(player.PlayerName, world.Name.ToString(), (ushort) world.RowId, chunk.Message!.ContentId, 0, 0);
|
|
}
|
|
|
|
LogWindow.Activate = true;
|
|
}
|
|
|
|
if (world.IsPublic) {
|
|
var party = Plugin.PartyList;
|
|
var leader = (ulong?) party[(int) party.PartyLeaderIndex]?.ContentId;
|
|
var isLeader = party.Length == 0 || Plugin.ClientState.LocalContentId == leader;
|
|
var member = party.FirstOrDefault(member => member.Name.TextValue == player.PlayerName && member.World.Id == world.RowId);
|
|
var isInParty = member != default;
|
|
var inInstance = LogWindow.Plugin.Functions.IsInInstance();
|
|
var inPartyInstance = TerritorySheet.GetRow(Plugin.ClientState.TerritoryType)?.TerritoryIntendedUse is (41 or 47 or 48 or 52 or 53);
|
|
if (isLeader) {
|
|
if (!isInParty) {
|
|
if (inInstance && inPartyInstance) {
|
|
if (validContentId && ImGui.Selectable(Language.Context_InviteToParty)) {
|
|
LogWindow.Plugin.Functions.Party.InviteInInstance(chunk.Message!.ContentId);
|
|
}
|
|
} else if (!inInstance && ImGui.BeginMenu(Language.Context_InviteToParty)) {
|
|
if (ImGui.Selectable(Language.Context_InviteToParty_SameWorld)) {
|
|
LogWindow.Plugin.Functions.Party.InviteSameWorld(player.PlayerName, (ushort) world.RowId, chunk.Message?.ContentId ?? 0);
|
|
}
|
|
|
|
if (validContentId && ImGui.Selectable(Language.Context_InviteToParty_DifferentWorld)) {
|
|
LogWindow.Plugin.Functions.Party.InviteOtherWorld(chunk.Message!.ContentId);
|
|
}
|
|
|
|
ImGui.EndMenu();
|
|
}
|
|
}
|
|
|
|
if (isInParty && member != null && (!inInstance || (inInstance && inPartyInstance))) {
|
|
if (ImGui.Selectable(Language.Context_Promote)) {
|
|
LogWindow.Plugin.Functions.Party.Promote(player.PlayerName, (ulong) member.ContentId);
|
|
}
|
|
|
|
if (ImGui.Selectable(Language.Context_KickFromParty)) {
|
|
LogWindow.Plugin.Functions.Party.Kick(player.PlayerName, (ulong) member.ContentId);
|
|
}
|
|
}
|
|
}
|
|
|
|
var isFriend = LogWindow.Plugin.Common.Functions.FriendList.List.Any(friend => friend.Name.TextValue == player.PlayerName && friend.HomeWorld == world.RowId);
|
|
if (!isFriend && ImGui.Selectable(Language.Context_SendFriendRequest)) {
|
|
LogWindow.Plugin.Functions.SendFriendRequest(player.PlayerName, (ushort) world.RowId);
|
|
}
|
|
|
|
if (ImGui.Selectable(Language.Context_AddToBlacklist)) {
|
|
LogWindow.Plugin.Functions.AddToBlacklist(player.PlayerName, (ushort) world.RowId);
|
|
}
|
|
|
|
if (LogWindow.Plugin.Functions.IsMentor() && ImGui.Selectable(Language.Context_InviteToNoviceNetwork)) {
|
|
LogWindow.Plugin.Functions.Context.InviteToNoviceNetwork(player.PlayerName, (ushort) world.RowId);
|
|
}
|
|
}
|
|
|
|
var inputChannel = chunk.Message?.Code.Type.ToInputChannel();
|
|
if (inputChannel != null && ImGui.Selectable(Language.Context_ReplyInSelectedChatMode)) {
|
|
LogWindow.SetChannel(inputChannel.Value);
|
|
LogWindow.Activate = true;
|
|
}
|
|
|
|
if (ImGui.Selectable(Language.Context_Target) && FindCharacterForPayload(player) is { } obj) {
|
|
Plugin.TargetManager.Target = obj;
|
|
}
|
|
|
|
if (validContentId && ImGui.Selectable(Language.Context_AdventurerPlate))
|
|
{
|
|
if (!LogWindow.Plugin.Functions.TryOpenAdventurerPlate(chunk.Message!.ContentId))
|
|
WrapperUtil.AddNotification(Language.Context_AdventurerPlateError, NotificationType.Warning);
|
|
}
|
|
|
|
// View Party Finder 0x2E
|
|
}
|
|
|
|
private PlayerCharacter? FindCharacterForPayload(PlayerPayload payload) {
|
|
foreach (var obj in Plugin.ObjectTable) {
|
|
if (obj is not PlayerCharacter character)
|
|
continue;
|
|
|
|
if (character.Name.TextValue != payload.PlayerName)
|
|
continue;
|
|
|
|
if (payload.World.IsPublic && character.HomeWorld.Id != payload.World.RowId)
|
|
continue;
|
|
|
|
return character;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|