Compare commits
57 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d6d746c1ed | |||
| 50a8dc6d09 | |||
| 6ad3faa922 | |||
| 64dd38a2a3 | |||
| e748ba7138 | |||
| 62ce794e8b | |||
| 0f6c3a5332 | |||
| ca638c19a2 | |||
| 2680d24a39 | |||
| 082e9e5580 | |||
| 004056b648 | |||
| ca28a9d6f7 | |||
| 83d705c4c6 | |||
| 5b75e305eb | |||
| 0669b2cecb | |||
| 3df83a8fa7 | |||
| e92662969b | |||
| 86686bf0ca | |||
| 8d92c79822 | |||
| 9900230520 | |||
| a9264fdd21 | |||
| 331bd63e2e | |||
| dfc85d7890 | |||
| ddd6954142 | |||
| 22c3497fec | |||
| 675225658c | |||
| 8273c68318 | |||
| 7f41e593c3 | |||
| ab3bf20ffa | |||
| 4b21e569a0 | |||
| bfd5cd1b12 | |||
| 83fdf5613e | |||
| 545a812b66 | |||
| cb2cd8e32c | |||
| e699a758f3 | |||
| e6e90cdcd3 | |||
| e7ce31dc0b | |||
| 1e9bd2484a | |||
| a4d3e8b0f3 | |||
| 5695a0823b | |||
| 22475d7223 | |||
| 348d8f50e6 | |||
| 5f78d24c78 | |||
| 0af7217e63 | |||
| e01ebcde37 | |||
| d127662959 | |||
| 8e7d49ca01 | |||
| 966ee43d87 | |||
| e6b7ad7351 | |||
| 95adfcd00f | |||
| 9738948a2a | |||
| 7272365630 | |||
| 94f7b003d2 | |||
| 3f849e69ef | |||
| c2b952ed0d | |||
| d6ae6772d5 | |||
| 442cdcb2ec |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -360,4 +360,7 @@ MigrationBackup/
|
|||||||
.ionide/
|
.ionide/
|
||||||
|
|
||||||
# Fody - auto-generated XML schema
|
# Fody - auto-generated XML schema
|
||||||
FodyWeavers.xsd
|
FodyWeavers.xsd
|
||||||
|
|
||||||
|
# Idea
|
||||||
|
.idea
|
||||||
|
|||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 Pilzinsel64
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -1,25 +1,18 @@
|
|||||||
using System;
|
namespace Pilz.Dalamud.ActivityContexts;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.ActivityContexts
|
public class ActivityContext
|
||||||
{
|
{
|
||||||
public class ActivityContext
|
public ActivityType ActivityType { get; init; }
|
||||||
|
public ZoneType ZoneType { get; init; }
|
||||||
|
|
||||||
|
public ActivityContext(ActivityType activityType, ZoneType zoneType)
|
||||||
{
|
{
|
||||||
public ActivityType ActivityType { get; init; }
|
ActivityType = activityType;
|
||||||
public ZoneType ZoneType { get; init; }
|
ZoneType = zoneType;
|
||||||
|
}
|
||||||
|
|
||||||
public ActivityContext(ActivityType activityType, ZoneType zoneType)
|
public bool IsInDuty
|
||||||
{
|
{
|
||||||
ActivityType = activityType;
|
get => ZoneType != ZoneType.Overworld;
|
||||||
ZoneType = zoneType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsInDuty
|
|
||||||
{
|
|
||||||
get => ZoneType != ZoneType.Overworld;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,89 +1,82 @@
|
|||||||
using Dalamud.Logging;
|
using Lumina.Excel;
|
||||||
using Lumina.Excel;
|
using Lumina.Excel.Sheets;
|
||||||
using Lumina.Excel.GeneratedSheets;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.ActivityContexts
|
namespace Pilz.Dalamud.ActivityContexts;
|
||||||
|
|
||||||
|
public class ActivityContextManager : IDisposable
|
||||||
{
|
{
|
||||||
public class ActivityContextManager : IDisposable
|
public delegate void ActivityContextChangedEventHandler(ActivityContextManager sender, ActivityContext activityContext);
|
||||||
|
public event ActivityContextChangedEventHandler ActivityContextChanged;
|
||||||
|
|
||||||
|
private readonly ExcelSheet<ContentFinderCondition> contentFinderConditionsSheet;
|
||||||
|
|
||||||
|
public ActivityContext CurrentActivityContext { get; protected set; }
|
||||||
|
|
||||||
|
public ActivityContextManager()
|
||||||
{
|
{
|
||||||
public delegate void ActivityContextChangedEventHandler(ActivityContextManager sender, ActivityContext activityContext);
|
// Get condition sheet
|
||||||
public event ActivityContextChangedEventHandler ActivityContextChanged;
|
contentFinderConditionsSheet = PluginServices.DataManager.GameData.GetExcelSheet<ContentFinderCondition>();
|
||||||
|
|
||||||
private readonly ExcelSheet<ContentFinderCondition> contentFinderConditionsSheet;
|
// Checks current territory type (if enabled/installed during a dutiy e.g.)
|
||||||
|
CheckCurrentTerritory();
|
||||||
|
|
||||||
public ActivityContext CurrentActivityContext { get; protected set; }
|
// Enable event for automatic checks
|
||||||
|
PluginServices.ClientState.TerritoryChanged += ClientState_TerritoryChanged;
|
||||||
|
}
|
||||||
|
|
||||||
public ActivityContextManager()
|
public void Dispose()
|
||||||
|
{
|
||||||
|
PluginServices.ClientState.TerritoryChanged -= ClientState_TerritoryChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClientState_TerritoryChanged(ushort obj)
|
||||||
|
{
|
||||||
|
CheckCurrentTerritory();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckCurrentTerritory()
|
||||||
|
{
|
||||||
|
var content = contentFinderConditionsSheet.FirstOrDefault(c => c.TerritoryType.RowId == PluginServices.ClientState.TerritoryType);
|
||||||
|
ActivityType newActivityContext;
|
||||||
|
ZoneType newZoneType;
|
||||||
|
|
||||||
|
if (content.RowId == 0)
|
||||||
{
|
{
|
||||||
// Get condition sheet
|
// No content found, so we must be on the overworld
|
||||||
contentFinderConditionsSheet = PluginServices.DataManager.GameData.GetExcelSheet<ContentFinderCondition>();
|
newActivityContext = ActivityType.None;
|
||||||
|
newZoneType = ZoneType.Overworld;
|
||||||
// Checks current territory type (if enabled/installed during a dutiy e.g.)
|
|
||||||
CheckCurrentTerritory();
|
|
||||||
|
|
||||||
// Enable event for automatic checks
|
|
||||||
PluginServices.ClientState.TerritoryChanged += ClientState_TerritoryChanged;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
public void Dispose()
|
|
||||||
{
|
{
|
||||||
PluginServices.ClientState.TerritoryChanged -= ClientState_TerritoryChanged;
|
if (content.PvP)
|
||||||
}
|
|
||||||
|
|
||||||
private void ClientState_TerritoryChanged(object? sender, ushort e)
|
|
||||||
{
|
|
||||||
CheckCurrentTerritory();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CheckCurrentTerritory()
|
|
||||||
{
|
|
||||||
var content = contentFinderConditionsSheet.FirstOrDefault(c => c.TerritoryType.Row == PluginServices.ClientState.TerritoryType);
|
|
||||||
ActivityType newActivityContext;
|
|
||||||
ZoneType newZoneType;
|
|
||||||
|
|
||||||
if (content == null)
|
|
||||||
{
|
{
|
||||||
// No content found, so we must be on the overworld
|
newActivityContext = ActivityType.PvpDuty;
|
||||||
newActivityContext = ActivityType.None;
|
newZoneType = ZoneType.Pvp;
|
||||||
newZoneType = ZoneType.Overworld;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (content.PvP)
|
newActivityContext = ActivityType.PveDuty;
|
||||||
{
|
|
||||||
newActivityContext = ActivityType.PvpDuty;
|
|
||||||
newZoneType = ZoneType.Pvp;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newActivityContext = ActivityType.PveDuty;
|
|
||||||
|
|
||||||
// Find correct member type
|
// Find correct member type
|
||||||
var memberType = content.ContentMemberType.Row;
|
var memberType = content.ContentMemberType.RowId;
|
||||||
if (content.RowId == 16 || content.RowId == 15)
|
if (content.RowId == 16 || content.RowId == 15)
|
||||||
memberType = 2; // Praetorium and Castrum Meridianum
|
memberType = 2; // Praetorium and Castrum Meridianum
|
||||||
else if (content.RowId == 735 || content.RowId == 778)
|
else if (content.RowId == 735 || content.RowId == 778)
|
||||||
memberType = 127; // Bozja
|
memberType = 127; // Bozja
|
||||||
|
|
||||||
// Check for ZoneType
|
// Check for ZoneType
|
||||||
newZoneType = memberType switch
|
newZoneType = memberType switch
|
||||||
{
|
{
|
||||||
2 => ZoneType.Doungen,
|
2 => ZoneType.Doungen,
|
||||||
3 => ZoneType.Raid,
|
3 => ZoneType.Raid,
|
||||||
4 => ZoneType.AllianceRaid,
|
4 => ZoneType.AllianceRaid,
|
||||||
127 => ZoneType.Foray,
|
127 => ZoneType.Foray,
|
||||||
_ => ZoneType.Doungen,
|
_ => ZoneType.Doungen,
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrentActivityContext = new(newActivityContext, newZoneType);
|
|
||||||
ActivityContextChanged?.Invoke(this, CurrentActivityContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CurrentActivityContext = new(newActivityContext, newZoneType);
|
||||||
|
ActivityContextChanged?.Invoke(this, CurrentActivityContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,12 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Converters;
|
using Newtonsoft.Json.Converters;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.ActivityContexts
|
namespace Pilz.Dalamud.ActivityContexts;
|
||||||
|
|
||||||
|
[JsonConverter(typeof(StringEnumConverter))]
|
||||||
|
public enum ActivityType
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(StringEnumConverter))]
|
None = 0x0,
|
||||||
public enum ActivityType
|
PveDuty = 0x1,
|
||||||
{
|
PvpDuty = 0x2
|
||||||
None = 0x0,
|
|
||||||
PveDuty = 0x1,
|
|
||||||
PvpDuty = 0x2
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,16 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Converters;
|
using Newtonsoft.Json.Converters;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.ActivityContexts
|
namespace Pilz.Dalamud.ActivityContexts;
|
||||||
|
|
||||||
|
[Flags, JsonConverter(typeof(StringEnumConverter))]
|
||||||
|
public enum ZoneType
|
||||||
{
|
{
|
||||||
[Flags, JsonConverter(typeof(StringEnumConverter))]
|
Overworld = 1,
|
||||||
public enum ZoneType
|
Doungen = 2,
|
||||||
{
|
Raid = 4,
|
||||||
Overworld = 1,
|
AllianceRaid = 8,
|
||||||
Doungen = 2,
|
Foray = 16,
|
||||||
Raid = 4,
|
Pvp = 32,
|
||||||
AllianceRaid = 8,
|
Everywhere = int.MaxValue
|
||||||
Foray = 16,
|
|
||||||
Pvp = 32,
|
|
||||||
Everywhere = int.MaxValue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,41 +1,44 @@
|
|||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using System;
|
using Lumina.Text.ReadOnly;
|
||||||
using System.Collections.Generic;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud
|
namespace Pilz.Dalamud;
|
||||||
|
|
||||||
|
public static class Extensions
|
||||||
{
|
{
|
||||||
public static class Extensions
|
/// <summary>
|
||||||
|
/// Removes a Payload from a given SeString.
|
||||||
|
/// Using <code>SeString.Payloads.Remove()</code> does not use the reference to compare for some reason. Tis is a workaround.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="seString"></param>
|
||||||
|
/// <param name="payload"></param>
|
||||||
|
public static void Remove(this SeString seString, Payload payload)
|
||||||
{
|
{
|
||||||
/// <summary>
|
Remove(seString.Payloads, payload);
|
||||||
/// Removes a Payload from a given SeString.
|
}
|
||||||
/// Using <code>SeString.Payloads.Remove()</code> does not use the reference to compare for some reason. Tis is a workaround.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="seString"></param>
|
|
||||||
/// <param name="payload"></param>
|
|
||||||
public static void Remove(this SeString seString, Payload payload)
|
|
||||||
{
|
|
||||||
Remove(seString.Payloads, payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes a Payload from a given list.
|
/// Removes a Payload from a given list.
|
||||||
/// Using <code>List.Remove()</code> does not use the reference to compare for some reason. Tis is a workaround.
|
/// Using <code>List.Remove()</code> does not use the reference to compare for some reason. Tis is a workaround.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="seString"></param>
|
/// <param name="payloads"></param>
|
||||||
/// <param name="payload"></param>
|
/// <param name="payload"></param>
|
||||||
public static void Remove(this List<Payload> payloads, Payload payload)
|
public static void Remove(this List<Payload> payloads, Payload payload)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < payloads.Count; i++)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < payloads.Count; i++)
|
if (ReferenceEquals(payloads[i], payload))
|
||||||
{
|
{
|
||||||
if (ReferenceEquals(payloads[i], payload))
|
payloads.RemoveAt(i);
|
||||||
{
|
break;
|
||||||
payloads.RemoveAt(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
public static string ParseString(this ReadOnlySeString readOnlySeString)
|
||||||
|
{
|
||||||
|
return Encoding.UTF8.GetString(readOnlySeString);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,153 +1,148 @@
|
|||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using FFXIVClientStructs.FFXIV.Client.System.Memory;
|
using FFXIVClientStructs.FFXIV.Client.System.Memory;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud
|
namespace Pilz.Dalamud;
|
||||||
|
|
||||||
|
public static class GameInterfaceHelper
|
||||||
{
|
{
|
||||||
public static class GameInterfaceHelper
|
public static SeString ReadSeString(IntPtr ptr)
|
||||||
{
|
{
|
||||||
public static SeString ReadSeString(IntPtr ptr)
|
if (ptr == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
if (ptr == IntPtr.Zero)
|
|
||||||
{
|
|
||||||
return new SeString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TryReadStringBytes(ptr, out var bytes) && bytes != null)
|
|
||||||
{
|
|
||||||
return SeString.Parse(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SeString();
|
return new SeString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool TryReadSeString(IntPtr ptr, out SeString? seString)
|
if (TryReadStringBytes(ptr, out var bytes) && bytes != null)
|
||||||
{
|
{
|
||||||
seString = null;
|
return SeString.Parse(bytes);
|
||||||
if (ptr == IntPtr.Zero)
|
}
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TryReadStringBytes(ptr, out var bytes) && bytes != null)
|
return new SeString();
|
||||||
{
|
}
|
||||||
seString = SeString.Parse(bytes);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public static bool TryReadSeString(IntPtr ptr, out SeString? seString)
|
||||||
|
{
|
||||||
|
seString = null;
|
||||||
|
if (ptr == IntPtr.Zero)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string? ReadString(IntPtr ptr)
|
if (TryReadStringBytes(ptr, out var bytes) && bytes != null)
|
||||||
{
|
{
|
||||||
if (ptr == IntPtr.Zero)
|
seString = SeString.Parse(bytes);
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TryReadStringBytes(ptr, out var bytes) && bytes != null)
|
|
||||||
{
|
|
||||||
return Encoding.UTF8.GetString(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryReadString(IntPtr ptr, out string? str)
|
|
||||||
{
|
|
||||||
str = null;
|
|
||||||
if (ptr == IntPtr.Zero)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TryReadStringBytes(ptr, out var bytes) && bytes != null)
|
|
||||||
{
|
|
||||||
str = Encoding.UTF8.GetString(bytes);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryReadStringBytes(IntPtr ptr, out byte[]? bytes)
|
|
||||||
{
|
|
||||||
bytes = null;
|
|
||||||
if (ptr == IntPtr.Zero)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var size = 0;
|
|
||||||
while (Marshal.ReadByte(ptr, size) != 0)
|
|
||||||
{
|
|
||||||
size++;
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes = new byte[size];
|
|
||||||
Marshal.Copy(ptr, bytes, 0, size);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IntPtr PluginAllocate(byte[] bytes)
|
return false;
|
||||||
{
|
}
|
||||||
IntPtr pointer = Marshal.AllocHGlobal(bytes.Length + 1);
|
|
||||||
Marshal.Copy(bytes, 0, pointer, bytes.Length);
|
|
||||||
Marshal.WriteByte(pointer, bytes.Length, 0);
|
|
||||||
|
|
||||||
return pointer;
|
public static string? ReadString(IntPtr ptr)
|
||||||
|
{
|
||||||
|
if (ptr == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IntPtr PluginAllocate(SeString seString)
|
if (TryReadStringBytes(ptr, out var bytes) && bytes != null)
|
||||||
{
|
{
|
||||||
return PluginAllocate(seString.Encode());
|
return Encoding.UTF8.GetString(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void PluginFree(IntPtr ptr)
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryReadString(IntPtr ptr, out string? str)
|
||||||
|
{
|
||||||
|
str = null;
|
||||||
|
if (ptr == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
Marshal.FreeHGlobal(ptr);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void PluginFree(ref IntPtr ptr)
|
if (TryReadStringBytes(ptr, out var bytes) && bytes != null)
|
||||||
{
|
{
|
||||||
PluginFree(ptr);
|
str = Encoding.UTF8.GetString(bytes);
|
||||||
ptr = IntPtr.Zero;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] NullTerminate(this byte[] bytes)
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryReadStringBytes(IntPtr ptr, out byte[]? bytes)
|
||||||
|
{
|
||||||
|
bytes = null;
|
||||||
|
if (ptr == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
if (bytes.Length == 0 || bytes[bytes.Length - 1] != 0)
|
return false;
|
||||||
{
|
|
||||||
var newBytes = new byte[bytes.Length + 1];
|
|
||||||
Array.Copy(bytes, newBytes, bytes.Length);
|
|
||||||
newBytes[^1] = 0;
|
|
||||||
|
|
||||||
return newBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe IntPtr GameUIAllocate(ulong size)
|
var size = 0;
|
||||||
|
while (Marshal.ReadByte(ptr, size) != 0)
|
||||||
{
|
{
|
||||||
return (IntPtr)IMemorySpace.GetUISpace()->Malloc(size, 0);
|
size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void GameFree(ref IntPtr ptr, ulong size)
|
bytes = new byte[size];
|
||||||
{
|
Marshal.Copy(ptr, bytes, 0, size);
|
||||||
if (ptr == IntPtr.Zero)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMemorySpace.Free((void*)ptr, size);
|
return true;
|
||||||
ptr = IntPtr.Zero;
|
}
|
||||||
|
|
||||||
|
public static IntPtr PluginAllocate(byte[] bytes)
|
||||||
|
{
|
||||||
|
IntPtr pointer = Marshal.AllocHGlobal(bytes.Length + 1);
|
||||||
|
Marshal.Copy(bytes, 0, pointer, bytes.Length);
|
||||||
|
Marshal.WriteByte(pointer, bytes.Length, 0);
|
||||||
|
|
||||||
|
return pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IntPtr PluginAllocate(SeString seString)
|
||||||
|
{
|
||||||
|
return PluginAllocate(seString.Encode());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void PluginFree(IntPtr ptr)
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void PluginFree(ref IntPtr ptr)
|
||||||
|
{
|
||||||
|
PluginFree(ptr);
|
||||||
|
ptr = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] NullTerminate(this byte[] bytes)
|
||||||
|
{
|
||||||
|
if (bytes.Length == 0 || bytes[bytes.Length - 1] != 0)
|
||||||
|
{
|
||||||
|
var newBytes = new byte[bytes.Length + 1];
|
||||||
|
Array.Copy(bytes, newBytes, bytes.Length);
|
||||||
|
newBytes[^1] = 0;
|
||||||
|
|
||||||
|
return newBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe IntPtr GameUIAllocate(ulong size)
|
||||||
|
{
|
||||||
|
return (IntPtr)IMemorySpace.GetUISpace()->Malloc(size, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe void GameFree(ref IntPtr ptr, ulong size)
|
||||||
|
{
|
||||||
|
if (ptr == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMemorySpace.Free((void*)ptr, size);
|
||||||
|
ptr = IntPtr.Zero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,19 @@
|
|||||||
using System;
|
namespace Pilz.Dalamud.Icons;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Icons
|
public class JobIconSet
|
||||||
{
|
{
|
||||||
public class JobIconSet
|
private readonly int[] icons;
|
||||||
|
|
||||||
|
public float IconScale { get; init; }
|
||||||
|
|
||||||
|
public JobIconSet(int[] icons, float iconScale)
|
||||||
{
|
{
|
||||||
private readonly int[] icons;
|
this.icons = icons;
|
||||||
|
IconScale = iconScale;
|
||||||
|
}
|
||||||
|
|
||||||
public float IconScale { get; init; }
|
public int GetIcon(uint jobID)
|
||||||
|
{
|
||||||
public JobIconSet(int[] icons, float iconScale)
|
return icons[jobID - 1];
|
||||||
{
|
|
||||||
this.icons = icons;
|
|
||||||
IconScale = iconScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetIcon(uint jobID)
|
|
||||||
{
|
|
||||||
return icons[jobID - 1];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,17 @@
|
|||||||
using System;
|
namespace Pilz.Dalamud.Icons;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Icons
|
public enum JobIconSetName
|
||||||
{
|
{
|
||||||
public enum JobIconSetName
|
Gold,
|
||||||
{
|
Framed,
|
||||||
Gold,
|
Glowing,
|
||||||
Framed,
|
Blue,
|
||||||
Glowing,
|
Red,
|
||||||
Blue,
|
Purple,
|
||||||
Red,
|
Black,
|
||||||
Purple,
|
Yellow,
|
||||||
Black,
|
Orange,
|
||||||
Yellow,
|
Green,
|
||||||
Orange,
|
Grey,
|
||||||
Green,
|
Role
|
||||||
Grey,
|
|
||||||
Role
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,128 +1,132 @@
|
|||||||
using Lumina.Excel.GeneratedSheets;
|
namespace Pilz.Dalamud.Icons;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Icons
|
public class JobIconSets
|
||||||
{
|
{
|
||||||
public class JobIconSets
|
private readonly Dictionary<JobIconSetName, JobIconSet> iconSets = [];
|
||||||
|
|
||||||
|
public JobIconSets()
|
||||||
{
|
{
|
||||||
private readonly Dictionary<JobIconSetName, JobIconSet> iconSets = new();
|
Add(JobIconSetName.Gold,
|
||||||
|
[
|
||||||
|
62001, 62002, 62003, 62004, 62005, 62006, 62007, 62008, 62009, 62010,
|
||||||
|
62011, 62012, 62013, 62014, 62015, 62016, 62017, 62018, 62019, 62020,
|
||||||
|
62021, 62022, 62023, 62024, 62025, 62026, 62027, 62028, 62029, 62030,
|
||||||
|
62031, 62032, 62033, 62034, 62035, 62036, 62037, 62038, 62039, 62040,
|
||||||
|
62041, 62042,
|
||||||
|
], 1);
|
||||||
|
|
||||||
public JobIconSets()
|
Add(JobIconSetName.Framed,
|
||||||
|
[
|
||||||
|
62101, 62102, 62103, 62104, 62105, 62106, 62107, 62108, 62109, 62110,
|
||||||
|
62111, 62112, 62113, 62114, 62115, 62116, 62117, 62118, 62119, 62120,
|
||||||
|
62121, 62122, 62123, 62124, 62125, 62126, 62127, 62128, 62129, 62130,
|
||||||
|
62131, 62132, 62133, 62134, 62135, 62136, 62137, 62138, 62139, 62140,
|
||||||
|
62141, 62142,
|
||||||
|
]);
|
||||||
|
|
||||||
|
Add(JobIconSetName.Glowing,
|
||||||
|
[
|
||||||
|
62301, 62302, 62303, 62304, 62305, 62306, 62307, 62310, 62311, 62312,
|
||||||
|
62313, 62314, 62315, 62316, 62317, 62318, 62319, 62320, 62401, 62402,
|
||||||
|
62403, 62404, 62405, 62406, 62407, 62308, 62408, 62409, 62309, 62410,
|
||||||
|
62411, 62412, 62413, 62414, 62415, 62416, 62417, 62418, 62419, 62420,
|
||||||
|
62421, 62422,
|
||||||
|
]);
|
||||||
|
|
||||||
|
Add(JobIconSetName.Grey,
|
||||||
|
[
|
||||||
|
91022, 91023, 91024, 91025, 91026, 91028, 91029, 91031, 91032, 91033,
|
||||||
|
91034, 91035, 91036, 91037, 91038, 91039, 91040, 91041, 91079, 91080,
|
||||||
|
91081, 91082, 91083, 91084, 91085, 91030, 91086, 91087, 91121, 91122,
|
||||||
|
91125, 91123, 91124, 91127, 91128, 91129, 91130, 91131, 91132, 91133,
|
||||||
|
91185, 91186,
|
||||||
|
], 2);
|
||||||
|
|
||||||
|
Add(JobIconSetName.Black,
|
||||||
|
[
|
||||||
|
91522, 91523, 91524, 91525, 91526, 91528, 91529, 91531, 91532, 91533,
|
||||||
|
91534, 91535, 91536, 91537, 91538, 91539, 91540, 91541, 91579, 91580,
|
||||||
|
91581, 91582, 91583, 91584, 91585, 91530, 91586, 91587, 91621, 91622,
|
||||||
|
91625, 91623, 91624, 91627, 91628, 91629, 91630, 91631, 91632, 91633,
|
||||||
|
91685, 91686,
|
||||||
|
], 2);
|
||||||
|
|
||||||
|
Add(JobIconSetName.Yellow,
|
||||||
|
[
|
||||||
|
92022, 92023, 92024, 92025, 92026, 92028, 92029, 92031, 92032, 92033,
|
||||||
|
92034, 92035, 92036, 92037, 92038, 92039, 92040, 92041, 92079, 92080,
|
||||||
|
92081, 92082, 92083, 92084, 92085, 92030, 92086, 92087, 92121, 92122,
|
||||||
|
92125, 92123, 92124, 92127, 92128, 92129, 92130, 92131, 92132, 92133,
|
||||||
|
92185, 92186,
|
||||||
|
], 2);
|
||||||
|
|
||||||
|
Add(JobIconSetName.Orange,
|
||||||
|
[
|
||||||
|
92522, 92523, 92524, 92525, 92526, 92528, 92529, 92531, 92532, 92533,
|
||||||
|
92534, 92535, 92536, 92537, 92538, 92539, 92540, 92541, 92579, 92580,
|
||||||
|
92581, 92582, 92583, 92584, 92585, 92530, 92586, 92587, 92621, 92622,
|
||||||
|
92625, 92623, 92624, 92627, 92628, 92629, 92630, 92631, 92632, 92633,
|
||||||
|
92685, 92686,
|
||||||
|
], 2);
|
||||||
|
|
||||||
|
Add(JobIconSetName.Red,
|
||||||
|
[
|
||||||
|
93022, 93023, 93024, 93025, 93026, 93028, 93029, 93031, 93032, 93033,
|
||||||
|
93034, 93035, 93036, 93037, 93038, 93039, 93040, 93041, 93079, 93080,
|
||||||
|
93081, 93082, 93083, 93084, 93085, 93030, 93086, 93087, 93121, 93122,
|
||||||
|
93125, 93123, 93124, 93127, 93128, 93129, 93130, 93131, 93132, 93133,
|
||||||
|
93185, 93186,
|
||||||
|
], 2);
|
||||||
|
|
||||||
|
Add(JobIconSetName.Purple, icons: new[]
|
||||||
{
|
{
|
||||||
Add(JobIconSetName.Gold, new[]
|
93522, 93523, 93524, 93525, 93526, 93528, 93529, 93531, 93532, 93533,
|
||||||
{
|
93534, 93535, 93536, 93537, 93538, 93539, 93540, 93541, 93579, 93580,
|
||||||
62001, 62002, 62003, 62004, 62005, 62006, 62007, 62008, 62009, 62010,
|
93581, 93582, 93583, 93584, 93585, 93530, 93586, 93587, 93621, 93622,
|
||||||
62011, 62012, 62013, 62014, 62015, 62016, 62017, 62018, 62019, 62020,
|
93625, 93623, 93624, 93627, 93628, 93629, 93630, 93631, 93632, 93633,
|
||||||
62021, 62022, 62023, 62024, 62025, 62026, 62027, 62028, 62029, 62030,
|
93685, 93686,
|
||||||
62031, 62032, 62033, 62034, 62035, 62036, 62037, 62038, 62039, 62040
|
}, scale: 2);
|
||||||
}, 1);
|
|
||||||
|
|
||||||
Add(JobIconSetName.Framed, new[]
|
Add(JobIconSetName.Blue,
|
||||||
{
|
[
|
||||||
62101, 62102, 62103, 62104, 62105, 62106, 62107, 62108, 62109, 62110,
|
94022, 94023, 94024, 94025, 94026, 94028, 94029, 94031, 94032, 94033,
|
||||||
62111, 62112, 62113, 62114, 62115, 62116, 62117, 62118, 62119, 62120,
|
94034, 94035, 94036, 94037, 94038, 94039, 94040, 94041, 94079, 94080,
|
||||||
62121, 62122, 62123, 62124, 62125, 62126, 62127, 62128, 62129, 62130,
|
94081, 94082, 94083, 94084, 94085, 94030, 94086, 94087, 94121, 94122,
|
||||||
62131, 62132, 62133, 62134, 62135, 62136, 62137, 62138, 62139, 62140
|
94125, 94123, 94124, 94127, 94128, 94129, 94130, 94131, 94132, 94133,
|
||||||
});
|
94185, 94186,
|
||||||
|
], 2);
|
||||||
|
|
||||||
Add(JobIconSetName.Glowing, new[]
|
Add(JobIconSetName.Green,
|
||||||
{
|
[
|
||||||
62301, 62302, 62303, 62304, 62305, 62306, 62307, 62310, 62311, 62312,
|
94522, 94523, 94524, 94525, 94526, 94528, 94529, 94531, 94532, 94533,
|
||||||
62313, 62314, 62315, 62316, 62317, 62318, 62319, 62320, 62401, 62402,
|
94534, 94535, 94536, 94537, 94538, 94539, 94540, 94541, 94579, 94580,
|
||||||
62403, 62404, 62405, 62406, 62407, 62308, 62408, 62409, 62309, 62410,
|
94581, 94582, 94583, 94584, 94585, 94530, 94586, 94587, 94621, 94622,
|
||||||
62411, 62412, 62413, 62414, 62415, 62416, 62417, 62418, 62419, 62420
|
94625, 94623, 94624, 94627, 94628, 94629, 94630, 94631, 94632, 94633,
|
||||||
});
|
94685, 94686,
|
||||||
|
], 2);
|
||||||
|
|
||||||
Add(JobIconSetName.Grey, new[]
|
Add(JobIconSetName.Role,
|
||||||
{
|
[
|
||||||
91022, 91023, 91024, 91025, 91026, 91028, 91029, 91031, 91032, 91033,
|
62581, 62584, 62581, 62584, 62586, 62582, 62502, 62502, 62503, 62504,
|
||||||
91034, 91035, 91036, 91037, 91038, 91039, 91040, 91041, 91079, 91080,
|
62505, 62506, 62507, 62508, 62509, 62510, 62511, 62512, 62581, 62584,
|
||||||
91081, 91082, 91083, 91084, 91085, 91030, 91086, 91087, 91121, 91122,
|
62581, 62584, 62586, 62582, 62587, 62587, 62587, 62582, 62584, 62584,
|
||||||
91125, 91123, 91124, 91127, 91128, 91129, 91130, 91131, 91132, 91133
|
62586, 62581, 62582, 62584, 62587, 62587, 62581, 62586, 62584, 62582,
|
||||||
}, 2);
|
62584, 62584,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
Add(JobIconSetName.Black, new[]
|
private void Add(JobIconSetName id, int[] icons, float scale = 1f)
|
||||||
{
|
{
|
||||||
91522, 91523, 91524, 91525, 91526, 91528, 91529, 91531, 91532, 91533,
|
iconSets[id] = new JobIconSet(icons, scale);
|
||||||
91534, 91535, 91536, 91537, 91538, 91539, 91540, 91541, 91579, 91580,
|
}
|
||||||
91581, 91582, 91583, 91584, 91585, 91530, 91586, 91587, 91621, 91622,
|
|
||||||
91625, 91623, 91624, 91627, 91628, 91629, 91630, 91631, 91632, 91633
|
|
||||||
}, 2);
|
|
||||||
|
|
||||||
Add(JobIconSetName.Yellow, new[]
|
public int GetJobIcon(JobIconSetName set, uint jobId)
|
||||||
{
|
{
|
||||||
92022, 92023, 92024, 92025, 92026, 92028, 92029, 92031, 92032, 92033,
|
return iconSets[set].GetIcon(jobId);
|
||||||
92034, 92035, 92036, 92037, 92038, 92039, 92040, 92041, 92079, 92080,
|
}
|
||||||
92081, 92082, 92083, 92084, 92085, 92030, 92086, 92087, 92121, 92122,
|
|
||||||
92125, 92123, 92124, 92127, 92128, 92129, 92130, 92131, 92132, 92133
|
|
||||||
}, 2);
|
|
||||||
|
|
||||||
Add(JobIconSetName.Orange, new[]
|
public float GetJobIconSale(JobIconSetName set)
|
||||||
{
|
{
|
||||||
92522, 92523, 92524, 92525, 92526, 92528, 92529, 92531, 92532, 92533,
|
return iconSets[set].IconScale;
|
||||||
92534, 92535, 92536, 92537, 92538, 92539, 92540, 92541, 92579, 92580,
|
|
||||||
92581, 92582, 92583, 92584, 92585, 92530, 92586, 92587, 92621, 92622,
|
|
||||||
92625, 92623, 92624, 92627, 92628, 92629, 92630, 92631, 92632, 92633
|
|
||||||
}, 2);
|
|
||||||
|
|
||||||
Add(JobIconSetName.Red, new[]
|
|
||||||
{
|
|
||||||
93022, 93023, 93024, 93025, 93026, 93028, 93029, 93031, 93032, 93033,
|
|
||||||
93034, 93035, 93036, 93037, 93038, 93039, 93040, 93041, 93079, 93080,
|
|
||||||
93081, 93082, 93083, 93084, 93085, 93030, 93086, 93087, 93121, 93122,
|
|
||||||
93125, 93123, 93124, 93127, 93128, 93129, 93130, 93131, 93132, 93133
|
|
||||||
}, 2);
|
|
||||||
|
|
||||||
Add(JobIconSetName.Purple, new[]
|
|
||||||
{
|
|
||||||
93522, 93523, 93524, 93525, 93526, 93528, 93529, 93531, 93532, 93533,
|
|
||||||
93534, 93535, 93536, 93537, 93538, 93539, 93540, 93541, 93579, 93580,
|
|
||||||
93581, 93582, 93583, 93584, 93585, 93530, 93586, 93587, 93621, 93622,
|
|
||||||
93625, 93623, 93624, 93627, 93628, 93629, 93630, 93631, 93632, 93633
|
|
||||||
}, 2);
|
|
||||||
|
|
||||||
Add(JobIconSetName.Blue, new[]
|
|
||||||
{
|
|
||||||
94022, 94023, 94024, 94025, 94026, 94028, 94029, 94031, 94032, 94033,
|
|
||||||
94034, 94035, 94036, 94037, 94038, 94039, 94040, 94041, 94079, 94080,
|
|
||||||
94081, 94082, 94083, 94084, 94085, 94030, 94086, 94087, 94121, 94122,
|
|
||||||
94125, 94123, 94124, 94127, 94128, 94129, 94130, 94131, 94132, 94133
|
|
||||||
}, 2);
|
|
||||||
|
|
||||||
Add(JobIconSetName.Green, new[]
|
|
||||||
{
|
|
||||||
94522, 94523, 94524, 94525, 94526, 94528, 94529, 94531, 94532, 94533,
|
|
||||||
94534, 94535, 94536, 94537, 94538, 94539, 94540, 94541, 94579, 94580,
|
|
||||||
94581, 94582, 94583, 94584, 94585, 94530, 94586, 94587, 94621, 94622,
|
|
||||||
94625, 94623, 94624, 94627, 94628, 94629, 94630, 94631, 94632, 94633
|
|
||||||
}, 2);
|
|
||||||
|
|
||||||
Add(JobIconSetName.Role, new[]
|
|
||||||
{
|
|
||||||
62581, 62584, 62581, 62584, 62586, 62582, 62502, 62502, 62503, 62504,
|
|
||||||
62505, 62506, 62507, 62508, 62509, 62510, 62511, 62512, 62581, 62584,
|
|
||||||
62581, 62584, 62586, 62582, 62587, 62587, 62587, 62582, 62584, 62584,
|
|
||||||
62586, 62581, 62582, 62584, 62587, 62587, 62581, 62586, 62584, 62582
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Add(JobIconSetName id, int[] icons, float scale = 1f)
|
|
||||||
{
|
|
||||||
iconSets[id] = new JobIconSet(icons, scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetJobIcon(JobIconSetName set, uint jobId)
|
|
||||||
{
|
|
||||||
return iconSets[set].GetIcon(jobId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public float GetJobIconSale(JobIconSetName set)
|
|
||||||
{
|
|
||||||
return iconSets[set].IconScale;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
25
Pilz.Dalamud/Icons/StatusIcons.cs
Normal file
25
Pilz.Dalamud/Icons/StatusIcons.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
|
|
||||||
|
namespace Pilz.Dalamud.Icons;
|
||||||
|
|
||||||
|
[JsonConverter(typeof(StringEnumConverter))]
|
||||||
|
public enum StatusIcons
|
||||||
|
{
|
||||||
|
Disconnecting = 061503,
|
||||||
|
InDuty = 061506,
|
||||||
|
ViewingCutscene = 061508,
|
||||||
|
Busy = 061509,
|
||||||
|
Idle = 061511,
|
||||||
|
DutyFinder = 061517,
|
||||||
|
PartyLeader = 061521,
|
||||||
|
PartyMember = 061522,
|
||||||
|
RolePlaying = 061545,
|
||||||
|
GroupPose = 061546,
|
||||||
|
NewAdventurer = 061523,
|
||||||
|
Mentor = 061540,
|
||||||
|
MentorPvE = 061542,
|
||||||
|
MentorCrafting = 061543,
|
||||||
|
MentorPvP = 061544,
|
||||||
|
Returner = 061547,
|
||||||
|
}
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Nameplates.EventArgs
|
|
||||||
{
|
|
||||||
public class AddonNamePlate_SetPlayerNameEventArgs : HookWithResultBaseEventArgs<IntPtr>
|
|
||||||
{
|
|
||||||
public IntPtr PlayerNameplateObjectPtr { get; set; }
|
|
||||||
public IntPtr TitlePtr { get; set; }
|
|
||||||
public IntPtr NamePtr { get; set; }
|
|
||||||
public IntPtr FreeCompanyPtr { get; set; }
|
|
||||||
public bool IsTitleAboveName { get; set; }
|
|
||||||
public bool IsTitleVisible { get; set; }
|
|
||||||
public int IconID { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
using Dalamud.Game.Text.SeStringHandling;
|
|
||||||
using Pilz.Dalamud.Nameplates.Model;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Nameplates.EventArgs
|
|
||||||
{
|
|
||||||
public class AddonNamePlate_SetPlayerNameManagedEventArgs : HookWithResultManagedBaseEventArgs<IntPtr>
|
|
||||||
{
|
|
||||||
public new AddonNamePlate_SetPlayerNameEventArgs OriginalEventArgs
|
|
||||||
{
|
|
||||||
get => base.OriginalEventArgs as AddonNamePlate_SetPlayerNameEventArgs;
|
|
||||||
set => base.OriginalEventArgs = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SafeNameplateObject SafeNameplateObject { get; set; }
|
|
||||||
public SeString Title { get; internal set; }
|
|
||||||
public SeString Name { get; internal set; }
|
|
||||||
public SeString FreeCompany { get; set; }
|
|
||||||
|
|
||||||
public bool IsTitleAboveName
|
|
||||||
{
|
|
||||||
get => OriginalEventArgs.IsTitleAboveName;
|
|
||||||
set => OriginalEventArgs.IsTitleAboveName = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsTitleVisible
|
|
||||||
{
|
|
||||||
get => OriginalEventArgs.IsTitleVisible;
|
|
||||||
set => OriginalEventArgs.IsTitleVisible = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int IconID
|
|
||||||
{
|
|
||||||
get => OriginalEventArgs.IconID;
|
|
||||||
set => OriginalEventArgs.IconID = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Nameplates.EventArgs
|
|
||||||
{
|
|
||||||
public abstract class HookBaseEventArgs
|
|
||||||
{
|
|
||||||
internal event Action CallOriginal;
|
|
||||||
|
|
||||||
public void Original()
|
|
||||||
{
|
|
||||||
CallOriginal?.Invoke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Nameplates.EventArgs
|
|
||||||
{
|
|
||||||
public abstract class HookManagedBaseEventArgs
|
|
||||||
{
|
|
||||||
public HookBaseEventArgs OriginalEventArgs { get; internal set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Nameplates.EventArgs
|
|
||||||
{
|
|
||||||
public abstract class HookWithResultBaseEventArgs<TResult>
|
|
||||||
{
|
|
||||||
internal event Func<TResult> CallOriginal;
|
|
||||||
|
|
||||||
public TResult Result { get; set; }
|
|
||||||
|
|
||||||
// Call Original based on the given properties
|
|
||||||
public TResult Original()
|
|
||||||
{
|
|
||||||
return CallOriginal.Invoke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Nameplates.EventArgs
|
|
||||||
{
|
|
||||||
public abstract class HookWithResultManagedBaseEventArgs<TResult>
|
|
||||||
{
|
|
||||||
public HookWithResultBaseEventArgs<TResult> OriginalEventArgs { get; internal set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
using Dalamud.Logging;
|
|
||||||
using Dalamud.Plugin;
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Nameplates.Model
|
|
||||||
{
|
|
||||||
public class SafeAddonNameplate
|
|
||||||
{
|
|
||||||
private readonly DalamudPluginInterface Interface;
|
|
||||||
|
|
||||||
public IntPtr Pointer => PluginServices.GameGui.GetAddonByName("NamePlate", 1);
|
|
||||||
|
|
||||||
public SafeAddonNameplate(DalamudPluginInterface pluginInterface)
|
|
||||||
{
|
|
||||||
Interface = pluginInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
public unsafe SafeNameplateObject GetNamePlateObject(int index)
|
|
||||||
{
|
|
||||||
SafeNameplateObject result = null;
|
|
||||||
|
|
||||||
if (Pointer != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
var npObjectArrayPtrPtr = Pointer + Marshal.OffsetOf(typeof(AddonNamePlate), nameof(AddonNamePlate.NamePlateObjectArray)).ToInt32();
|
|
||||||
var npObjectArrayPtr = Marshal.ReadIntPtr(npObjectArrayPtrPtr);
|
|
||||||
|
|
||||||
if (npObjectArrayPtr != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
var npObjectPtr = npObjectArrayPtr + Marshal.SizeOf(typeof(AddonNamePlate.NamePlateObject)) * index;
|
|
||||||
result = new(npObjectPtr, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
using FFXIVClientStructs.FFXIV.Client.System.String;
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Nameplates.Model
|
|
||||||
{
|
|
||||||
public class SafeNameplateInfo
|
|
||||||
{
|
|
||||||
public readonly IntPtr Pointer;
|
|
||||||
public readonly RaptureAtkModule.NamePlateInfo Data;
|
|
||||||
|
|
||||||
public SafeNameplateInfo(IntPtr pointer)
|
|
||||||
{
|
|
||||||
Pointer = pointer;
|
|
||||||
Data = Marshal.PtrToStructure<RaptureAtkModule.NamePlateInfo>(Pointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal IntPtr NameAddress => GetStringPtr(nameof(RaptureAtkModule.NamePlateInfo.Name));
|
|
||||||
internal IntPtr FcNameAddress => GetStringPtr(nameof(RaptureAtkModule.NamePlateInfo.FcName));
|
|
||||||
internal IntPtr TitleAddress => GetStringPtr(nameof(RaptureAtkModule.NamePlateInfo.Title));
|
|
||||||
internal IntPtr DisplayTitleAddress => GetStringPtr(nameof(RaptureAtkModule.NamePlateInfo.DisplayTitle));
|
|
||||||
internal IntPtr LevelTextAddress => GetStringPtr(nameof(RaptureAtkModule.NamePlateInfo.LevelText));
|
|
||||||
|
|
||||||
public string Name => GetString(NameAddress);
|
|
||||||
public string FcName => GetString(FcNameAddress);
|
|
||||||
public string Title => GetString(TitleAddress);
|
|
||||||
public string DisplayTitle => GetString(DisplayTitleAddress);
|
|
||||||
public string LevelText => GetString(LevelTextAddress);
|
|
||||||
|
|
||||||
//public bool IsPlayerCharacter() => XivApi.IsPlayerCharacter(Data.ObjectID.ObjectID);
|
|
||||||
|
|
||||||
//public bool IsPartyMember() => XivApi.IsPartyMember(Data.ObjectID.ObjectID);
|
|
||||||
|
|
||||||
//public bool IsAllianceMember() => XivApi.IsAllianceMember(Data.ObjectID.ObjectID);
|
|
||||||
|
|
||||||
//public uint GetJobID() => GetJobId(Data.ObjectID.ObjectID);
|
|
||||||
|
|
||||||
private unsafe IntPtr GetStringPtr(string name)
|
|
||||||
{
|
|
||||||
var namePtr = Pointer + Marshal.OffsetOf(typeof(RaptureAtkModule.NamePlateInfo), name).ToInt32();
|
|
||||||
var stringPtrPtr = namePtr + Marshal.OffsetOf(typeof(Utf8String), nameof(Utf8String.StringPtr)).ToInt32();
|
|
||||||
var stringPtr = Marshal.ReadIntPtr(stringPtrPtr);
|
|
||||||
return stringPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetString(IntPtr stringPtr)
|
|
||||||
{
|
|
||||||
return Marshal.PtrToStringUTF8(stringPtr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
using Dalamud.Logging;
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Nameplates.Model
|
|
||||||
{
|
|
||||||
public class SafeNameplateObject
|
|
||||||
{
|
|
||||||
public IntPtr Pointer { get; }
|
|
||||||
public AddonNamePlate.NamePlateObject Data { get; }
|
|
||||||
|
|
||||||
private int _Index;
|
|
||||||
private SafeNameplateInfo _NamePlateInfo;
|
|
||||||
|
|
||||||
public SafeNameplateObject(IntPtr pointer, int index = -1)
|
|
||||||
{
|
|
||||||
Pointer = pointer;
|
|
||||||
Data = Marshal.PtrToStructure<AddonNamePlate.NamePlateObject>(pointer);
|
|
||||||
_Index = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Index
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
int result = _Index;
|
|
||||||
|
|
||||||
if (_Index == -1)
|
|
||||||
{
|
|
||||||
var addon = XivApi.GetSafeAddonNamePlate();
|
|
||||||
var npObject0 = addon.GetNamePlateObject(0);
|
|
||||||
|
|
||||||
if (npObject0 == null)
|
|
||||||
result = -1; // NamePlateObject0 was null
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var npObjectBase = npObject0.Pointer;
|
|
||||||
var npObjectSize = Marshal.SizeOf(typeof(AddonNamePlate.NamePlateObject));
|
|
||||||
var index = (Pointer.ToInt64() - npObjectBase.ToInt64()) / npObjectSize;
|
|
||||||
|
|
||||||
if (index < 0 || index >= 50)
|
|
||||||
result = -2; // NamePlateObject index was out of bounds
|
|
||||||
else
|
|
||||||
result = _Index = (int)index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public SafeNameplateInfo NamePlateInfo
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
SafeNameplateInfo result = null;
|
|
||||||
|
|
||||||
if (_NamePlateInfo != null)
|
|
||||||
{
|
|
||||||
var rapturePtr = XivApi.RaptureAtkModulePtr;
|
|
||||||
|
|
||||||
if (rapturePtr != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
var npInfoArrayPtr = rapturePtr + Marshal.OffsetOf(typeof(RaptureAtkModule), nameof(RaptureAtkModule.NamePlateInfoArray)).ToInt32();
|
|
||||||
var npInfoPtr = npInfoArrayPtr + Marshal.SizeOf(typeof(RaptureAtkModule.NamePlateInfo)) * Index;
|
|
||||||
result = _NamePlateInfo = new SafeNameplateInfo(npInfoPtr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Getters
|
|
||||||
|
|
||||||
public unsafe IntPtr IconImageNodeAddress => Marshal.ReadIntPtr(Pointer + Marshal.OffsetOf(typeof(AddonNamePlate.NamePlateObject), nameof(AddonNamePlate.NamePlateObject.IconImageNode)).ToInt32());
|
|
||||||
public unsafe IntPtr NameNodeAddress => Marshal.ReadIntPtr(Pointer + Marshal.OffsetOf(typeof(AddonNamePlate.NamePlateObject), nameof(AddonNamePlate.NamePlateObject.NameText)).ToInt32());
|
|
||||||
|
|
||||||
public AtkImageNode IconImageNode => Marshal.PtrToStructure<AtkImageNode>(IconImageNodeAddress);
|
|
||||||
public AtkTextNode NameTextNode => Marshal.PtrToStructure<AtkTextNode>(NameNodeAddress);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public unsafe bool IsVisible => Data.IsVisible;
|
|
||||||
public unsafe bool IsLocalPlayer => Data.IsLocalPlayer;
|
|
||||||
public bool IsPlayer => Data.NameplateKind == 0;
|
|
||||||
|
|
||||||
//public void SetIconScale(float scale, bool force = false)
|
|
||||||
//{
|
|
||||||
// if (force || IconImageNode.AtkResNode.ScaleX != scale || IconImageNode.AtkResNode.ScaleY != scale)
|
|
||||||
// {
|
|
||||||
// Instance.SetNodeScale(IconImageNodeAddress, scale, scale);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public void SetNameScale(float scale, bool force = false)
|
|
||||||
//{
|
|
||||||
// if (force || NameTextNode.AtkResNode.ScaleX != scale || NameTextNode.AtkResNode.ScaleY != scale)
|
|
||||||
// {
|
|
||||||
// Instance.SetNodeScale(NameNodeAddress, scale, scale);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public unsafe void SetName(IntPtr ptr)
|
|
||||||
//{
|
|
||||||
// NameTextNode.SetText("aaa");
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public void SetIcon(int icon)
|
|
||||||
//{
|
|
||||||
// IconImageNode.LoadIconTexture(icon, 1);
|
|
||||||
//}
|
|
||||||
|
|
||||||
public void SetIconPosition(short x, short y)
|
|
||||||
{
|
|
||||||
var iconXAdjustPtr = Pointer + Marshal.OffsetOf(typeof(AddonNamePlate.NamePlateObject), nameof(AddonNamePlate.NamePlateObject.IconXAdjust)).ToInt32();
|
|
||||||
var iconYAdjustPtr = Pointer + Marshal.OffsetOf(typeof(AddonNamePlate.NamePlateObject), nameof(AddonNamePlate.NamePlateObject.IconYAdjust)).ToInt32();
|
|
||||||
Marshal.WriteInt16(iconXAdjustPtr, x);
|
|
||||||
Marshal.WriteInt16(iconYAdjustPtr, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Converters;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Nameplates.Model
|
|
||||||
{
|
|
||||||
[JsonConverter(typeof(StringEnumConverter))]
|
|
||||||
public enum StatusIcons
|
|
||||||
{
|
|
||||||
Disconnecting = 061503,
|
|
||||||
InDuty = 061506,
|
|
||||||
ViewingCutscene = 061508,
|
|
||||||
Busy = 061509,
|
|
||||||
Idle = 061511,
|
|
||||||
DutyFinder = 061517,
|
|
||||||
PartyLeader = 061521,
|
|
||||||
PartyMember = 061522,
|
|
||||||
RolePlaying = 061545,
|
|
||||||
GroupPose = 061546,
|
|
||||||
NewAdventurer = 061523,
|
|
||||||
Mentor = 061540,
|
|
||||||
MentorPvE = 061542,
|
|
||||||
MentorCrafting = 061543,
|
|
||||||
MentorPvP = 061544,
|
|
||||||
Returner = 061547,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,203 +0,0 @@
|
|||||||
using Dalamud.Hooking;
|
|
||||||
using Pilz.Dalamud.Nameplates.EventArgs;
|
|
||||||
using Dalamud.Utility.Signatures;
|
|
||||||
using ImGuiNET;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Pilz.Dalamud.Nameplates.Model;
|
|
||||||
using Lumina.Excel.GeneratedSheets;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Nameplates
|
|
||||||
{
|
|
||||||
public class NameplateHooks : IDisposable
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Will be executed when the the Game wants to update the content of a nameplate with the details of the Player.
|
|
||||||
/// </summary>
|
|
||||||
public event AddonNamePlate_SetPlayerNameEventHandler AddonNamePlate_SetPlayerName;
|
|
||||||
public delegate void AddonNamePlate_SetPlayerNameEventHandler(AddonNamePlate_SetPlayerNameEventArgs eventArgs);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Will be executed when the the Game wants to update the content of a nameplate with the details of the Player.
|
|
||||||
/// This will event acts on a higher level with SeString instead of IntPtr e.g.
|
|
||||||
/// </summary>
|
|
||||||
public event AddonNamePlate_SetPlayerNameManagedEventHandler AddonNamePlate_SetPlayerNameManaged;
|
|
||||||
public delegate void AddonNamePlate_SetPlayerNameManagedEventHandler(AddonNamePlate_SetPlayerNameManagedEventArgs eventArgs);
|
|
||||||
|
|
||||||
[Signature("48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 54 41 56 41 57 48 83 EC 40 44 0F B6 E2", DetourName = nameof(SetPlayerNameplateDetour))]
|
|
||||||
private readonly Hook<AddonNamePlate_SetPlayerNameplateDetour>? hook_AddonNamePlate_SetPlayerNameplateDetour = null;
|
|
||||||
private unsafe delegate IntPtr AddonNamePlate_SetPlayerNameplateDetour(IntPtr playerNameplateObjectPtr, bool isTitleAboveName, bool isTitleVisible, IntPtr titlePtr, IntPtr namePtr, IntPtr freeCompanyPtr, int iconId);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines if all hooks are enabled. If this is false, then there might be something wrong or the class already has been disposed.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsValid
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var isValid = true;
|
|
||||||
|
|
||||||
isValid &= IsHookEnabled(hook_AddonNamePlate_SetPlayerNameplateDetour);
|
|
||||||
|
|
||||||
return isValid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create a new instance of NAmeplateHooks and automatically initialize and enable all Hooks.
|
|
||||||
/// </summary>
|
|
||||||
public NameplateHooks()
|
|
||||||
{
|
|
||||||
SignatureHelper.Initialise(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
~NameplateHooks()
|
|
||||||
{
|
|
||||||
Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Unhook();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initialize and enable all Hooks.
|
|
||||||
/// </summary>
|
|
||||||
internal void Initialize()
|
|
||||||
{
|
|
||||||
hook_AddonNamePlate_SetPlayerNameplateDetour?.Enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disable all Hooks.
|
|
||||||
/// </summary>
|
|
||||||
internal void Unhook()
|
|
||||||
{
|
|
||||||
hook_AddonNamePlate_SetPlayerNameplateDetour?.Disable();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsHookEnabled<T>(Hook<T> hook) where T : Delegate
|
|
||||||
{
|
|
||||||
return hook != null && hook.IsEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IntPtr SetPlayerNameplateDetour(IntPtr playerNameplateObjectPtr, bool isTitleAboveName, bool isTitleVisible, IntPtr titlePtr, IntPtr namePtr, IntPtr freeCompanyPtr, int iconId)
|
|
||||||
{
|
|
||||||
var result = IntPtr.Zero;
|
|
||||||
|
|
||||||
if (IsHookEnabled(hook_AddonNamePlate_SetPlayerNameplateDetour))
|
|
||||||
{
|
|
||||||
var eventArgs = new AddonNamePlate_SetPlayerNameEventArgs
|
|
||||||
{
|
|
||||||
PlayerNameplateObjectPtr = playerNameplateObjectPtr,
|
|
||||||
TitlePtr = titlePtr,
|
|
||||||
NamePtr = namePtr,
|
|
||||||
FreeCompanyPtr = freeCompanyPtr,
|
|
||||||
IsTitleAboveName = isTitleAboveName,
|
|
||||||
IsTitleVisible = isTitleVisible,
|
|
||||||
IconID = iconId
|
|
||||||
};
|
|
||||||
|
|
||||||
void callOriginal()
|
|
||||||
{
|
|
||||||
eventArgs.Result = eventArgs.Original();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add handler for the Original call
|
|
||||||
eventArgs.CallOriginal += () =>
|
|
||||||
{
|
|
||||||
return hook_AddonNamePlate_SetPlayerNameplateDetour.Original(
|
|
||||||
eventArgs.PlayerNameplateObjectPtr,
|
|
||||||
eventArgs.IsTitleAboveName,
|
|
||||||
eventArgs.IsTitleVisible,
|
|
||||||
eventArgs.TitlePtr,
|
|
||||||
eventArgs.NamePtr,
|
|
||||||
eventArgs.FreeCompanyPtr,
|
|
||||||
eventArgs.IconID);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Invoke Event
|
|
||||||
var hasDefaultHookEvent = AddonNamePlate_SetPlayerName != null;
|
|
||||||
AddonNamePlate_SetPlayerName?.Invoke(eventArgs);
|
|
||||||
|
|
||||||
if (AddonNamePlate_SetPlayerNameManaged != null)
|
|
||||||
{
|
|
||||||
var freeTitle = false;
|
|
||||||
var freeName = false;
|
|
||||||
var freeFreeCompany = false;
|
|
||||||
|
|
||||||
// Create NamePlateObject if possible
|
|
||||||
var namePlateObj = new SafeNameplateObject(playerNameplateObjectPtr);
|
|
||||||
|
|
||||||
// Create new event
|
|
||||||
var managedEventArgs = new AddonNamePlate_SetPlayerNameManagedEventArgs
|
|
||||||
{
|
|
||||||
OriginalEventArgs = eventArgs,
|
|
||||||
SafeNameplateObject = namePlateObj,
|
|
||||||
Title = GameInterfaceHelper.ReadSeString(eventArgs.TitlePtr),
|
|
||||||
Name = GameInterfaceHelper.ReadSeString(eventArgs.NamePtr),
|
|
||||||
FreeCompany = GameInterfaceHelper.ReadSeString(eventArgs.FreeCompanyPtr)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get raw string content
|
|
||||||
var titleRaw = managedEventArgs.Title.Encode();
|
|
||||||
var nameRaw = managedEventArgs.Name.Encode();
|
|
||||||
var freeCompanyRaw = managedEventArgs.FreeCompany.Encode();
|
|
||||||
|
|
||||||
// Invoke Managed Event
|
|
||||||
AddonNamePlate_SetPlayerNameManaged.Invoke(managedEventArgs);
|
|
||||||
|
|
||||||
// Get new Title string ontent
|
|
||||||
var titleNewRaw = managedEventArgs.Title.Encode();
|
|
||||||
if (!titleRaw.SequenceEqual(titleNewRaw))
|
|
||||||
{
|
|
||||||
eventArgs.TitlePtr = GameInterfaceHelper.PluginAllocate(titleNewRaw);
|
|
||||||
freeTitle = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get new Name string ontent
|
|
||||||
var nameNewRaw = managedEventArgs.Name.Encode();
|
|
||||||
if (!nameRaw.SequenceEqual(nameNewRaw))
|
|
||||||
{
|
|
||||||
eventArgs.NamePtr = GameInterfaceHelper.PluginAllocate(nameNewRaw);
|
|
||||||
freeName = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get new Free Company string ontent
|
|
||||||
var freeCompanyNewRaw = managedEventArgs.FreeCompany.Encode();
|
|
||||||
if (!freeCompanyRaw.SequenceEqual(freeCompanyNewRaw))
|
|
||||||
{
|
|
||||||
eventArgs.FreeCompanyPtr = GameInterfaceHelper.PluginAllocate(freeCompanyNewRaw);
|
|
||||||
freeFreeCompany = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call Original as we changed something
|
|
||||||
callOriginal();
|
|
||||||
|
|
||||||
// Free memory
|
|
||||||
if (freeTitle)
|
|
||||||
GameInterfaceHelper.PluginFree(eventArgs.TitlePtr);
|
|
||||||
if (freeName)
|
|
||||||
GameInterfaceHelper.PluginFree(eventArgs.NamePtr);
|
|
||||||
if (freeFreeCompany)
|
|
||||||
GameInterfaceHelper.PluginFree(eventArgs.FreeCompanyPtr);
|
|
||||||
}
|
|
||||||
else if(!hasDefaultHookEvent)
|
|
||||||
{
|
|
||||||
// Call original in case of nothing get called, just to get secure it will not break the game when not calling it.
|
|
||||||
callOriginal();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set result
|
|
||||||
result = eventArgs.Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
using Dalamud.Hooking;
|
|
||||||
using Pilz.Dalamud.Nameplates.EventArgs;
|
|
||||||
using Dalamud.Utility.Signatures;
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using Dalamud.Game.ClientState.Objects.Types;
|
|
||||||
using Pilz.Dalamud.Nameplates.Model;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Nameplates
|
|
||||||
{
|
|
||||||
public class NameplateManager : IDisposable
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Provides events that you can hook to.
|
|
||||||
/// </summary>
|
|
||||||
public NameplateHooks Hooks { get; init; } = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines if all hooks are enabled and the NameplateManager is ready to go. If this is false, then there might be something wrong or something already has been disposed.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsValid => Hooks.IsValid;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new instance of the NameplateManager.
|
|
||||||
/// </summary>
|
|
||||||
public NameplateManager()
|
|
||||||
{
|
|
||||||
Hooks.Initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
~NameplateManager()
|
|
||||||
{
|
|
||||||
Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Hooks?.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static T? GetNameplateGameObject<T>(SafeNameplateObject namePlateObject) where T : GameObject
|
|
||||||
{
|
|
||||||
return GetNameplateGameObject<T>(namePlateObject.Pointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static T? GetNameplateGameObject<T>(IntPtr nameplateObjectPtr) where T : GameObject
|
|
||||||
{
|
|
||||||
// Get the nameplate object array
|
|
||||||
var nameplateAddonPtr = PluginServices.GameGui.GetAddonByName("NamePlate", 1);
|
|
||||||
var nameplateObjectArrayPtrPtr = nameplateAddonPtr + Marshal.OffsetOf(typeof(AddonNamePlate), nameof(AddonNamePlate.NamePlateObjectArray)).ToInt32();
|
|
||||||
var nameplateObjectArrayPtr = Marshal.ReadIntPtr(nameplateObjectArrayPtrPtr);
|
|
||||||
if (nameplateObjectArrayPtr == IntPtr.Zero)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine the index of the nameplate object within the nameplate object array
|
|
||||||
var namePlateObjectSize = Marshal.SizeOf(typeof(AddonNamePlate.NamePlateObject));
|
|
||||||
var namePlateObjectPtr0 = nameplateObjectArrayPtr + namePlateObjectSize * 0;
|
|
||||||
var namePlateIndex = (nameplateObjectPtr.ToInt64() - namePlateObjectPtr0.ToInt64()) / namePlateObjectSize;
|
|
||||||
if (namePlateIndex < 0 || namePlateIndex >= AddonNamePlate.NumNamePlateObjects)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the nameplate info array
|
|
||||||
IntPtr nameplateInfoArrayPtr = IntPtr.Zero;
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
var framework = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework.Instance();
|
|
||||||
nameplateInfoArrayPtr = new IntPtr(&framework->GetUiModule()->GetRaptureAtkModule()->NamePlateInfoArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the nameplate info for the nameplate object
|
|
||||||
var namePlateInfoPtr = new IntPtr(nameplateInfoArrayPtr.ToInt64() + Marshal.SizeOf(typeof(RaptureAtkModule.NamePlateInfo)) * namePlateIndex);
|
|
||||||
RaptureAtkModule.NamePlateInfo namePlateInfo = Marshal.PtrToStructure<RaptureAtkModule.NamePlateInfo>(namePlateInfoPtr);
|
|
||||||
|
|
||||||
// Return the object for its object id
|
|
||||||
var objectId = namePlateInfo.ObjectID.ObjectID;
|
|
||||||
return PluginServices.ObjectTable.SearchById(objectId) as T;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Pilz.Dalamud.Tools.Strings;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Nameplates.Tools
|
|
||||||
{
|
|
||||||
public class NameplateChanges
|
|
||||||
{
|
|
||||||
private readonly Dictionary<NameplateElements, StringChangesProps> changes = new();
|
|
||||||
|
|
||||||
public NameplateChanges()
|
|
||||||
{
|
|
||||||
changes.Add(NameplateElements.Title, new());
|
|
||||||
changes.Add(NameplateElements.Name, new());
|
|
||||||
changes.Add(NameplateElements.FreeCompany, new());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the properties with the changes of an element of your choice where you can add your payloads to a change and setup some options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="element">The position of your choice.</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public StringChangesProps GetProps(NameplateElements element)
|
|
||||||
{
|
|
||||||
return changes[element];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the changes of an element of your choice where you can add your payloads to a change.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="element">The position of your choice.</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public StringChanges GetChanges(NameplateElements element)
|
|
||||||
{
|
|
||||||
return GetProps(element).StringChanges;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a change of the position of the element of your choice where you can add your payloads.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="element">The position of your choice.</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public StringChange GetChange(NameplateElements element, StringPosition position)
|
|
||||||
{
|
|
||||||
return GetChanges(element).GetChange(position);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Nameplates.Tools
|
|
||||||
{
|
|
||||||
public class NameplateChangesProps
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// All the changes to the nameplate that should be made.
|
|
||||||
/// </summary>
|
|
||||||
public NameplateChanges Changes { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Nameplates.Tools
|
|
||||||
{
|
|
||||||
public enum NameplateElements
|
|
||||||
{
|
|
||||||
Name,
|
|
||||||
Title,
|
|
||||||
FreeCompany
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
using Dalamud.Game.Text.SeStringHandling;
|
|
||||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
|
||||||
using Pilz.Dalamud.ActivityContexts;
|
|
||||||
using Pilz.Dalamud.Nameplates.Model;
|
|
||||||
using Pilz.Dalamud.Tools;
|
|
||||||
using Pilz.Dalamud.Tools.Strings;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Nameplates.Tools
|
|
||||||
{
|
|
||||||
public static class NameplateUpdateFactory
|
|
||||||
{
|
|
||||||
public static void ApplyNameplateChanges(NameplateChangesProps props)
|
|
||||||
{
|
|
||||||
foreach (NameplateElements element in Enum.GetValues(typeof(NameplateElements)))
|
|
||||||
{
|
|
||||||
var change = props.Changes.GetProps(element);
|
|
||||||
StringUpdateFactory.ApplyStringChanges(change);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool ApplyStatusIconWithPrio(ref int statusIcon, int newStatusIcon, StringChange stringChange, ActivityContext activityContext, StatusIconPriorizer priorizer, bool moveIconToNameplateIfPossible)
|
|
||||||
{
|
|
||||||
bool? isPrio = null;
|
|
||||||
var fontIcon = StatusIconFontConverter.GetBitmapFontIconFromStatusIcon((StatusIcons)statusIcon);
|
|
||||||
|
|
||||||
if (moveIconToNameplateIfPossible)
|
|
||||||
{
|
|
||||||
if (fontIcon != null)
|
|
||||||
{
|
|
||||||
// Set new font icon as string change
|
|
||||||
var iconPayload = new IconPayload(fontIcon.Value);
|
|
||||||
stringChange.Payloads.Insert(0, iconPayload);
|
|
||||||
|
|
||||||
// If we moved it, we don't need it as icon anymore, yay :D
|
|
||||||
isPrio = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isPrio ??= priorizer.IsPriorityIcon(statusIcon, activityContext);
|
|
||||||
|
|
||||||
if (!isPrio.Value)
|
|
||||||
statusIcon = newStatusIcon;
|
|
||||||
|
|
||||||
return isPrio.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
using Lumina.Excel.GeneratedSheets;
|
|
||||||
using Pilz.Dalamud.ActivityContexts;
|
|
||||||
using Pilz.Dalamud.Nameplates.Model;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Nameplates.Tools
|
|
||||||
{
|
|
||||||
public class StatusIconPriorizer
|
|
||||||
{
|
|
||||||
private static StatusIconPriorizerSettings DefaultSettings { get; } = new();
|
|
||||||
public StatusIconPriorizerSettings Settings { get; init; }
|
|
||||||
|
|
||||||
public StatusIconPriorizer() : this(DefaultSettings)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public StatusIconPriorizer(StatusIconPriorizerSettings settings)
|
|
||||||
{
|
|
||||||
Settings = settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Check for an icon that should take priority over the job icon,
|
|
||||||
/// taking into account whether or not the player is in a duty.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="iconId">The incoming icon id that is being overwritten by the plugin.</param>
|
|
||||||
/// <param name="priorityIconId">The icon id that should be used.</param>
|
|
||||||
/// <returns>Whether a priority icon was found.</returns>
|
|
||||||
public bool IsPriorityIcon(int iconId, ActivityContext activityContext)
|
|
||||||
{
|
|
||||||
bool isPrioIcon;
|
|
||||||
|
|
||||||
if (!Settings.UsePriorizedIcons && iconId != (int)StatusIcons.Disconnecting && iconId != (int)StatusIcons.Disconnecting + 50)
|
|
||||||
isPrioIcon = false;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Select which set of priority icons to use based on whether we're in a duty
|
|
||||||
// In the future, there can be a third list used when in combat
|
|
||||||
var priorityIcons = GetPriorityIcons(activityContext);
|
|
||||||
|
|
||||||
// Determine whether the incoming icon should take priority over the job icon
|
|
||||||
// Check the id plus 50 as that's an alternately sized version
|
|
||||||
isPrioIcon = priorityIcons.Contains(iconId) || priorityIcons.Contains(iconId + 50);
|
|
||||||
}
|
|
||||||
|
|
||||||
return isPrioIcon;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<int> GetPriorityIcons(ActivityContext activityContext)
|
|
||||||
{
|
|
||||||
StatusIconPriorizerConditionSets set;
|
|
||||||
|
|
||||||
if (activityContext.ZoneType == ZoneType.Foray)
|
|
||||||
set = StatusIconPriorizerConditionSets.InForay;
|
|
||||||
else if (activityContext.IsInDuty)
|
|
||||||
set = StatusIconPriorizerConditionSets.InDuty;
|
|
||||||
else
|
|
||||||
set = StatusIconPriorizerConditionSets.Overworld;
|
|
||||||
|
|
||||||
return Settings.GetConditionSet(set).Select(n => (int)n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Nameplates.Tools
|
|
||||||
{
|
|
||||||
public enum StatusIconPriorizerConditionSets
|
|
||||||
{
|
|
||||||
Overworld,
|
|
||||||
InDuty,
|
|
||||||
InForay
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
using Pilz.Dalamud.ActivityContexts;
|
|
||||||
using Pilz.Dalamud.Nameplates.Model;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Nameplates.Tools
|
|
||||||
{
|
|
||||||
public class StatusIconPriorizerSettings
|
|
||||||
{
|
|
||||||
[JsonProperty("IconConditionSets")]
|
|
||||||
private Dictionary<StatusIconPriorizerConditionSets, List<StatusIcons>> iconConditionSets = new();
|
|
||||||
public bool UsePriorizedIcons { get; set; } = true;
|
|
||||||
|
|
||||||
[JsonConstructor]
|
|
||||||
private StatusIconPriorizerSettings(JsonConstructorAttribute dummy)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public StatusIconPriorizerSettings() : this(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public StatusIconPriorizerSettings(bool fillWithDefaultSettings)
|
|
||||||
{
|
|
||||||
foreach (StatusIconPriorizerConditionSets set in Enum.GetValues(typeof(StatusIconPriorizerConditionSets)))
|
|
||||||
iconConditionSets.Add(set, new List<StatusIcons>());
|
|
||||||
|
|
||||||
if (fillWithDefaultSettings)
|
|
||||||
FillWithDefaultSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<StatusIcons> GetConditionSet(StatusIconPriorizerConditionSets set)
|
|
||||||
{
|
|
||||||
return iconConditionSets[set];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ResetToEmpty()
|
|
||||||
{
|
|
||||||
foreach (var kvp in iconConditionSets)
|
|
||||||
kvp.Value.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ResetToDefault()
|
|
||||||
{
|
|
||||||
ResetToEmpty();
|
|
||||||
FillWithDefaultSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FillWithDefaultSettings()
|
|
||||||
{
|
|
||||||
var setOverworld = GetConditionSet(StatusIconPriorizerConditionSets.Overworld);
|
|
||||||
setOverworld.AddRange(new[]
|
|
||||||
{
|
|
||||||
StatusIcons.Disconnecting, // Disconnecting
|
|
||||||
StatusIcons.InDuty, // In Duty
|
|
||||||
StatusIcons.ViewingCutscene, // Viewing Cutscene
|
|
||||||
StatusIcons.Busy, // Busy
|
|
||||||
StatusIcons.Idle, // Idle
|
|
||||||
StatusIcons.DutyFinder, // Duty Finder
|
|
||||||
StatusIcons.PartyLeader, // Party Leader
|
|
||||||
StatusIcons.PartyMember, // Party Member
|
|
||||||
StatusIcons.RolePlaying, // Role Playing
|
|
||||||
StatusIcons.GroupPose, // Group Pose
|
|
||||||
StatusIcons.Mentor,
|
|
||||||
StatusIcons.MentorCrafting,
|
|
||||||
StatusIcons.MentorPvE,
|
|
||||||
StatusIcons.MentorPvP,
|
|
||||||
StatusIcons.Returner,
|
|
||||||
StatusIcons.NewAdventurer,
|
|
||||||
});
|
|
||||||
|
|
||||||
var setInDuty = GetConditionSet(StatusIconPriorizerConditionSets.InDuty);
|
|
||||||
setInDuty.AddRange(new[]
|
|
||||||
{
|
|
||||||
StatusIcons.Disconnecting, // Disconnecting
|
|
||||||
StatusIcons.ViewingCutscene, // Viewing Cutscene
|
|
||||||
StatusIcons.Idle, // Idle
|
|
||||||
StatusIcons.GroupPose, // Group Pose
|
|
||||||
StatusIcons.Mentor,
|
|
||||||
StatusIcons.MentorCrafting,
|
|
||||||
StatusIcons.MentorPvE,
|
|
||||||
StatusIcons.MentorPvP,
|
|
||||||
StatusIcons.Returner,
|
|
||||||
StatusIcons.NewAdventurer,
|
|
||||||
});
|
|
||||||
|
|
||||||
var setInForay = GetConditionSet(StatusIconPriorizerConditionSets.InForay);
|
|
||||||
setInForay.AddRange(new[]
|
|
||||||
{
|
|
||||||
// This allows you to see which players don't have a party
|
|
||||||
StatusIcons.InDuty, // In Duty
|
|
||||||
|
|
||||||
StatusIcons.Disconnecting, // Disconnecting
|
|
||||||
StatusIcons.ViewingCutscene, // Viewing Cutscene
|
|
||||||
StatusIcons.Idle, // Idle
|
|
||||||
StatusIcons.GroupPose, // Group Pose
|
|
||||||
StatusIcons.Mentor,
|
|
||||||
StatusIcons.MentorCrafting,
|
|
||||||
StatusIcons.MentorPvE,
|
|
||||||
StatusIcons.MentorPvP,
|
|
||||||
StatusIcons.Returner,
|
|
||||||
StatusIcons.NewAdventurer,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,61 +1,33 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Dalamud.NET.Sdk/13.0.0">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0-windows</TargetFramework>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>annotations</Nullable>
|
<Nullable>annotations</Nullable>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
<LangVersion>latest</LangVersion>
|
<Use_DalamudPackager>false</Use_DalamudPackager>
|
||||||
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
|
|
||||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
|
||||||
<Platforms>x64</Platforms>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
|
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<Copyright>Pilzinsel64</Copyright>
|
||||||
</PropertyGroup>
|
<PackageProjectUrl>https://github.com/Pilzinsel64/Pilz.Dalamud</PackageProjectUrl>
|
||||||
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
<PropertyGroup>
|
<RepositoryUrl>https://github.com/Pilzinsel64/Pilz.Dalamud</RepositoryUrl>
|
||||||
<DalamudLibPath>$(appdata)\XIVLauncher\addon\Hooks\dev\</DalamudLibPath>
|
<RepositoryType>git</RepositoryType>
|
||||||
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
<Version>1.0.3</Version>
|
||||||
<Copyright>Pilzinsel64</Copyright>
|
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||||
<PackageProjectUrl>https://github.com/Pilzinsel64/Pilz.Dalamud</PackageProjectUrl>
|
</PropertyGroup>
|
||||||
<RepositoryUrl>https://github.com/Pilzinsel64/Pilz.Dalamud</RepositoryUrl>
|
|
||||||
<RepositoryType>git</RepositoryType>
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<Version>0.3.0</Version>
|
<NoWarn>1701;1702;1591</NoWarn>
|
||||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
</PropertyGroup>
|
||||||
</PropertyGroup>
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<ItemGroup>
|
<NoWarn>1701;1702;1591</NoWarn>
|
||||||
<Reference Include="FFXIVClientStructs">
|
</PropertyGroup>
|
||||||
<HintPath>$(DalamudLibPath)FFXIVClientStructs.dll</HintPath>
|
|
||||||
<Private>false</Private>
|
<ItemGroup>
|
||||||
</Reference>
|
<None Include="..\README.md" Pack="true" PackagePath="\" />
|
||||||
<Reference Include="Newtonsoft.Json">
|
</ItemGroup>
|
||||||
<HintPath>$(DalamudLibPath)Newtonsoft.Json.dll</HintPath>
|
|
||||||
<Private>false</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Dalamud">
|
|
||||||
<HintPath>$(DalamudLibPath)Dalamud.dll</HintPath>
|
|
||||||
<Private>false</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="ImGui.NET">
|
|
||||||
<HintPath>$(DalamudLibPath)ImGui.NET.dll</HintPath>
|
|
||||||
<Private>false</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="ImGuiScene">
|
|
||||||
<HintPath>$(DalamudLibPath)ImGuiScene.dll</HintPath>
|
|
||||||
<Private>false</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Lumina">
|
|
||||||
<HintPath>$(DalamudLibPath)Lumina.dll</HintPath>
|
|
||||||
<Private>false</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Lumina.Excel">
|
|
||||||
<HintPath>$(DalamudLibPath)Lumina.Excel.dll</HintPath>
|
|
||||||
<Private>false</Private>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,28 +1,21 @@
|
|||||||
using Dalamud.Data;
|
using Dalamud.IoC;
|
||||||
using Dalamud.Game.ClientState;
|
|
||||||
using Dalamud.Game.ClientState.Objects;
|
|
||||||
using Dalamud.Game.Gui;
|
|
||||||
using Dalamud.IoC;
|
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using System;
|
using Dalamud.Plugin.Services;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud
|
namespace Pilz.Dalamud;
|
||||||
|
|
||||||
|
public class PluginServices
|
||||||
{
|
{
|
||||||
public class PluginServices
|
[PluginService] public static IDalamudPluginInterface PluginInterface { get; set; }
|
||||||
{
|
[PluginService] public static IGameGui GameGui { get; set; }
|
||||||
[PluginService] public static GameGui GameGui { get; set; } = null;
|
[PluginService] public static IClientState ClientState { get; set; }
|
||||||
[PluginService] public static DalamudPluginInterface PluginInterface { get; set; } = null;
|
[PluginService] public static IDataManager DataManager { get; set; }
|
||||||
[PluginService] public static ClientState ClientState { get; set; } = null;
|
[PluginService] public static IObjectTable ObjectTable { get; set; }
|
||||||
[PluginService] public static DataManager DataManager { get; set; } = null;
|
[PluginService] public static IGameInteropProvider GameInteropProvider { get; set; }
|
||||||
[PluginService] public static ObjectTable ObjectTable { get; set; } = null;
|
[PluginService] public static IAddonLifecycle AddonLifecycle { get; set; }
|
||||||
|
|
||||||
public static void Initialize(DalamudPluginInterface dalamudPluginInterface)
|
public static void Initialize(IDalamudPluginInterface dalamudPluginInterface)
|
||||||
{
|
{
|
||||||
dalamudPluginInterface.Create<PluginServices>();
|
dalamudPluginInterface.Create<PluginServices>();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
25
Pilz.Dalamud/Tools/NamePlates/NameplateChanges.cs
Normal file
25
Pilz.Dalamud/Tools/NamePlates/NameplateChanges.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using Dalamud.Game.Gui.NamePlate;
|
||||||
|
|
||||||
|
namespace Pilz.Dalamud.Tools.NamePlates;
|
||||||
|
|
||||||
|
public class NameplateChanges
|
||||||
|
{
|
||||||
|
private readonly List<NameplateElementChange> changes = [];
|
||||||
|
|
||||||
|
public NameplateChanges(INamePlateUpdateHandler handler)
|
||||||
|
{
|
||||||
|
changes.Add(new(NameplateElements.Title, handler));
|
||||||
|
changes.Add(new(NameplateElements.Name, handler));
|
||||||
|
changes.Add(new(NameplateElements.FreeCompany, handler));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the properties with the changes of an element of your choice where you can add your payloads to a change and setup some options.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="element">The position of your choice.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public NameplateElementChange GetChange(NameplateElements element)
|
||||||
|
{
|
||||||
|
return changes.FirstOrDefault(n => n.Element == element);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
Pilz.Dalamud/Tools/NamePlates/NameplateChangesProps.cs
Normal file
18
Pilz.Dalamud/Tools/NamePlates/NameplateChangesProps.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
namespace Pilz.Dalamud.Tools.NamePlates;
|
||||||
|
|
||||||
|
public class NameplateChangesProps
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// All the changes to the nameplate that should be made.
|
||||||
|
/// </summary>
|
||||||
|
public NameplateChanges Changes { get; set; }
|
||||||
|
|
||||||
|
public NameplateChangesProps()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public NameplateChangesProps(NameplateChanges changes) : this()
|
||||||
|
{
|
||||||
|
Changes = changes;
|
||||||
|
}
|
||||||
|
}
|
||||||
47
Pilz.Dalamud/Tools/NamePlates/NameplateElementChange.cs
Normal file
47
Pilz.Dalamud/Tools/NamePlates/NameplateElementChange.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using Dalamud.Game.Gui.NamePlate;
|
||||||
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
|
using Pilz.Dalamud.Tools.Strings;
|
||||||
|
|
||||||
|
namespace Pilz.Dalamud.Tools.NamePlates;
|
||||||
|
|
||||||
|
public class NameplateElementChange(NameplateElements element, INamePlateUpdateHandler handler)
|
||||||
|
{
|
||||||
|
public NameplateElements Element => element;
|
||||||
|
public StringChanges Changes { get; set; } = new();
|
||||||
|
|
||||||
|
public void ApplyFormatting(SeString prefix, SeString postfix)
|
||||||
|
{
|
||||||
|
var parts = (prefix, postfix);
|
||||||
|
|
||||||
|
switch (element)
|
||||||
|
{
|
||||||
|
case NameplateElements.Name:
|
||||||
|
handler.NameParts.TextWrap = parts;
|
||||||
|
break;
|
||||||
|
case NameplateElements.Title:
|
||||||
|
handler.TitleParts.OuterWrap = parts;
|
||||||
|
break;
|
||||||
|
case NameplateElements.FreeCompany:
|
||||||
|
handler.FreeCompanyTagParts.OuterWrap = parts;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ApplyChanges()
|
||||||
|
{
|
||||||
|
if (Changes.Any())
|
||||||
|
{
|
||||||
|
StringUpdateFactory.ApplyStringChanges(new()
|
||||||
|
{
|
||||||
|
StringChanges = Changes,
|
||||||
|
Destination = element switch
|
||||||
|
{
|
||||||
|
NameplateElements.Name => handler.NameParts.Text ??= handler.InfoView.Name,
|
||||||
|
NameplateElements.Title => handler.TitleParts.Text ??= handler.InfoView.Title,
|
||||||
|
NameplateElements.FreeCompany => handler.FreeCompanyTagParts.Text ??= handler.InfoView.FreeCompanyTag,
|
||||||
|
_ => null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
Pilz.Dalamud/Tools/NamePlates/NameplateElements.cs
Normal file
8
Pilz.Dalamud/Tools/NamePlates/NameplateElements.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Pilz.Dalamud.Tools.NamePlates;
|
||||||
|
|
||||||
|
public enum NameplateElements
|
||||||
|
{
|
||||||
|
Name,
|
||||||
|
Title,
|
||||||
|
FreeCompany,
|
||||||
|
}
|
||||||
48
Pilz.Dalamud/Tools/NamePlates/NameplateUpdateFactory.cs
Normal file
48
Pilz.Dalamud/Tools/NamePlates/NameplateUpdateFactory.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
using Dalamud.Game.Gui.NamePlate;
|
||||||
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
|
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||||
|
using Pilz.Dalamud.ActivityContexts;
|
||||||
|
using Pilz.Dalamud.Icons;
|
||||||
|
|
||||||
|
namespace Pilz.Dalamud.Tools.NamePlates;
|
||||||
|
|
||||||
|
public static class NameplateUpdateFactory
|
||||||
|
{
|
||||||
|
public static void ApplyNameplateChanges(NameplateChangesProps props)
|
||||||
|
{
|
||||||
|
foreach (NameplateElements element in Enum.GetValues(typeof(NameplateElements)))
|
||||||
|
{
|
||||||
|
var change = props.Changes.GetChange(element);
|
||||||
|
change.ApplyChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ApplyStatusIconWithPrio(INamePlateUpdateHandler handler, int newStatusIcon, ActivityContext activityContext, StatusIconPriorizer priorizer, bool moveIconToNameplateIfPossible)
|
||||||
|
{
|
||||||
|
bool? isPrio = null;
|
||||||
|
var fontIcon = StatusIconFontConverter.GetBitmapFontIconFromStatusIcon((StatusIcons)handler.NameIconId);
|
||||||
|
|
||||||
|
if (moveIconToNameplateIfPossible)
|
||||||
|
{
|
||||||
|
if (fontIcon != null)
|
||||||
|
{
|
||||||
|
// Set new font icon as string change
|
||||||
|
var icon = new IconPayload(fontIcon.Value); ;
|
||||||
|
if (handler.StatusPrefix is SeString str)
|
||||||
|
str.Payloads.Insert(0, icon);
|
||||||
|
else
|
||||||
|
handler.StatusPrefix = SeString.Empty.Append(icon);
|
||||||
|
|
||||||
|
// If we moved it, we don't need it as icon anymore, yay :D
|
||||||
|
isPrio = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isPrio ??= priorizer.IsPriorityIcon(handler.NameIconId, activityContext);
|
||||||
|
|
||||||
|
if (!isPrio.Value)
|
||||||
|
handler.NameIconId = newStatusIcon;
|
||||||
|
|
||||||
|
return isPrio.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
60
Pilz.Dalamud/Tools/NamePlates/StatusIconPriorizer.cs
Normal file
60
Pilz.Dalamud/Tools/NamePlates/StatusIconPriorizer.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using Pilz.Dalamud.ActivityContexts;
|
||||||
|
using Pilz.Dalamud.Icons;
|
||||||
|
|
||||||
|
namespace Pilz.Dalamud.Tools.NamePlates;
|
||||||
|
|
||||||
|
public class StatusIconPriorizer
|
||||||
|
{
|
||||||
|
private static StatusIconPriorizerSettings DefaultSettings { get; } = new();
|
||||||
|
public StatusIconPriorizerSettings Settings { get; init; }
|
||||||
|
|
||||||
|
public StatusIconPriorizer() : this(DefaultSettings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public StatusIconPriorizer(StatusIconPriorizerSettings settings)
|
||||||
|
{
|
||||||
|
Settings = settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check for an icon that should take priority over the job icon,
|
||||||
|
/// taking into account whether or not the player is in a duty.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="iconId">The incoming icon id that is being overwritten by the plugin.</param>
|
||||||
|
/// <param name="activityContext"></param>
|
||||||
|
/// <returns>Whether a priority icon was found.</returns>
|
||||||
|
public bool IsPriorityIcon(int iconId, ActivityContext activityContext)
|
||||||
|
{
|
||||||
|
bool isPrioIcon;
|
||||||
|
|
||||||
|
if (!Settings.UsePriorizedIcons && iconId != (int)StatusIcons.Disconnecting && iconId != (int)StatusIcons.Disconnecting + 50)
|
||||||
|
isPrioIcon = false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Select which set of priority icons to use based on whether we're in a duty
|
||||||
|
// In the future, there can be a third list used when in combat
|
||||||
|
var priorityIcons = GetPriorityIcons(activityContext);
|
||||||
|
|
||||||
|
// Determine whether the incoming icon should take priority over the job icon
|
||||||
|
// Check the id plus 50 as that's an alternately sized version
|
||||||
|
isPrioIcon = priorityIcons.Contains(iconId) || priorityIcons.Contains(iconId + 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
return isPrioIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<int> GetPriorityIcons(ActivityContext activityContext)
|
||||||
|
{
|
||||||
|
StatusIconPriorizerConditionSets set;
|
||||||
|
|
||||||
|
if (activityContext.ZoneType == ZoneType.Foray)
|
||||||
|
set = StatusIconPriorizerConditionSets.InForay;
|
||||||
|
else if (activityContext.IsInDuty)
|
||||||
|
set = StatusIconPriorizerConditionSets.InDuty;
|
||||||
|
else
|
||||||
|
set = StatusIconPriorizerConditionSets.Overworld;
|
||||||
|
|
||||||
|
return Settings.GetConditionSet(set).Select(n => (int)n);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Pilz.Dalamud.Tools.NamePlates;
|
||||||
|
|
||||||
|
public enum StatusIconPriorizerConditionSets
|
||||||
|
{
|
||||||
|
Overworld,
|
||||||
|
InDuty,
|
||||||
|
InForay
|
||||||
|
}
|
||||||
103
Pilz.Dalamud/Tools/NamePlates/StatusIconPriorizerSettings.cs
Normal file
103
Pilz.Dalamud/Tools/NamePlates/StatusIconPriorizerSettings.cs
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Pilz.Dalamud.Icons;
|
||||||
|
|
||||||
|
namespace Pilz.Dalamud.Tools.NamePlates;
|
||||||
|
|
||||||
|
public class StatusIconPriorizerSettings
|
||||||
|
{
|
||||||
|
[JsonProperty("IconConditionSets")]
|
||||||
|
private Dictionary<StatusIconPriorizerConditionSets, List<StatusIcons>> iconConditionSets = [];
|
||||||
|
public bool UsePriorizedIcons { get; set; } = true;
|
||||||
|
|
||||||
|
[JsonConstructor]
|
||||||
|
private StatusIconPriorizerSettings(JsonConstructorAttribute dummy)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public StatusIconPriorizerSettings() : this(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public StatusIconPriorizerSettings(bool fillWithDefaultSettings)
|
||||||
|
{
|
||||||
|
foreach (StatusIconPriorizerConditionSets set in Enum.GetValues(typeof(StatusIconPriorizerConditionSets)))
|
||||||
|
iconConditionSets.Add(set, []);
|
||||||
|
|
||||||
|
if (fillWithDefaultSettings)
|
||||||
|
FillWithDefaultSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<StatusIcons> GetConditionSet(StatusIconPriorizerConditionSets set)
|
||||||
|
{
|
||||||
|
return iconConditionSets[set];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetToEmpty()
|
||||||
|
{
|
||||||
|
foreach (var kvp in iconConditionSets)
|
||||||
|
kvp.Value.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetToDefault()
|
||||||
|
{
|
||||||
|
ResetToEmpty();
|
||||||
|
FillWithDefaultSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FillWithDefaultSettings()
|
||||||
|
{
|
||||||
|
var setOverworld = GetConditionSet(StatusIconPriorizerConditionSets.Overworld);
|
||||||
|
setOverworld.AddRange(new[]
|
||||||
|
{
|
||||||
|
StatusIcons.Disconnecting, // Disconnecting
|
||||||
|
StatusIcons.InDuty, // In Duty
|
||||||
|
StatusIcons.ViewingCutscene, // Viewing Cutscene
|
||||||
|
StatusIcons.Busy, // Busy
|
||||||
|
StatusIcons.Idle, // Idle
|
||||||
|
StatusIcons.DutyFinder, // Duty Finder
|
||||||
|
StatusIcons.PartyLeader, // Party Leader
|
||||||
|
StatusIcons.PartyMember, // Party Member
|
||||||
|
StatusIcons.RolePlaying, // Role Playing
|
||||||
|
StatusIcons.GroupPose, // Group Pose
|
||||||
|
StatusIcons.Mentor,
|
||||||
|
StatusIcons.MentorCrafting,
|
||||||
|
StatusIcons.MentorPvE,
|
||||||
|
StatusIcons.MentorPvP,
|
||||||
|
StatusIcons.Returner,
|
||||||
|
StatusIcons.NewAdventurer,
|
||||||
|
});
|
||||||
|
|
||||||
|
var setInDuty = GetConditionSet(StatusIconPriorizerConditionSets.InDuty);
|
||||||
|
setInDuty.AddRange(new[]
|
||||||
|
{
|
||||||
|
StatusIcons.Disconnecting, // Disconnecting
|
||||||
|
StatusIcons.ViewingCutscene, // Viewing Cutscene
|
||||||
|
StatusIcons.Idle, // Idle
|
||||||
|
StatusIcons.GroupPose, // Group Pose
|
||||||
|
StatusIcons.Mentor,
|
||||||
|
StatusIcons.MentorCrafting,
|
||||||
|
StatusIcons.MentorPvE,
|
||||||
|
StatusIcons.MentorPvP,
|
||||||
|
StatusIcons.Returner,
|
||||||
|
StatusIcons.NewAdventurer,
|
||||||
|
});
|
||||||
|
|
||||||
|
var setInForay = GetConditionSet(StatusIconPriorizerConditionSets.InForay);
|
||||||
|
setInForay.AddRange(new[]
|
||||||
|
{
|
||||||
|
// This allows you to see which players don't have a party
|
||||||
|
StatusIcons.InDuty, // In Duty
|
||||||
|
|
||||||
|
StatusIcons.Disconnecting, // Disconnecting
|
||||||
|
StatusIcons.ViewingCutscene, // Viewing Cutscene
|
||||||
|
StatusIcons.Idle, // Idle
|
||||||
|
StatusIcons.GroupPose, // Group Pose
|
||||||
|
StatusIcons.Mentor,
|
||||||
|
StatusIcons.MentorCrafting,
|
||||||
|
StatusIcons.MentorPvE,
|
||||||
|
StatusIcons.MentorPvP,
|
||||||
|
StatusIcons.Returner,
|
||||||
|
StatusIcons.NewAdventurer,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,41 +1,35 @@
|
|||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using Pilz.Dalamud.Nameplates.Model;
|
using Pilz.Dalamud.Icons;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Tools
|
namespace Pilz.Dalamud.Tools;
|
||||||
|
|
||||||
|
public static class StatusIconFontConverter
|
||||||
{
|
{
|
||||||
public static class StatusIconFontConverter
|
public static StatusIcons? GetStatusIconFromBitmapFontIcon(BitmapFontIcon fontIcon)
|
||||||
{
|
{
|
||||||
public static StatusIcons? GetStatusIconFromBitmapFontIcon(BitmapFontIcon fontIcon)
|
return fontIcon switch
|
||||||
{
|
{
|
||||||
return fontIcon switch
|
BitmapFontIcon.NewAdventurer => StatusIcons.NewAdventurer,
|
||||||
{
|
BitmapFontIcon.Mentor => StatusIcons.Mentor,
|
||||||
BitmapFontIcon.NewAdventurer => StatusIcons.NewAdventurer,
|
BitmapFontIcon.MentorPvE => StatusIcons.MentorPvE,
|
||||||
BitmapFontIcon.Mentor => StatusIcons.Mentor,
|
BitmapFontIcon.MentorCrafting => StatusIcons.MentorCrafting,
|
||||||
BitmapFontIcon.MentorPvE => StatusIcons.MentorPvE,
|
BitmapFontIcon.MentorPvP => StatusIcons.MentorPvP,
|
||||||
BitmapFontIcon.MentorCrafting => StatusIcons.MentorCrafting,
|
BitmapFontIcon.Returner => StatusIcons.Returner,
|
||||||
BitmapFontIcon.MentorPvP => StatusIcons.MentorPvP,
|
_ => null
|
||||||
BitmapFontIcon.Returner => StatusIcons.Returner,
|
};
|
||||||
_ => null
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BitmapFontIcon? GetBitmapFontIconFromStatusIcon(StatusIcons icon)
|
public static BitmapFontIcon? GetBitmapFontIconFromStatusIcon(StatusIcons icon)
|
||||||
|
{
|
||||||
|
return icon switch
|
||||||
{
|
{
|
||||||
return icon switch
|
StatusIcons.NewAdventurer => BitmapFontIcon.NewAdventurer,
|
||||||
{
|
StatusIcons.Mentor => BitmapFontIcon.Mentor,
|
||||||
StatusIcons.NewAdventurer => BitmapFontIcon.NewAdventurer,
|
StatusIcons.MentorPvE => BitmapFontIcon.MentorPvE,
|
||||||
StatusIcons.Mentor => BitmapFontIcon.Mentor,
|
StatusIcons.MentorCrafting => BitmapFontIcon.MentorCrafting,
|
||||||
StatusIcons.MentorPvE => BitmapFontIcon.MentorPvE,
|
StatusIcons.MentorPvP => BitmapFontIcon.MentorPvP,
|
||||||
StatusIcons.MentorCrafting => BitmapFontIcon.MentorCrafting,
|
StatusIcons.Returner => BitmapFontIcon.Returner,
|
||||||
StatusIcons.MentorPvP => BitmapFontIcon.MentorPvP,
|
_ => null
|
||||||
StatusIcons.Returner => BitmapFontIcon.Returner,
|
};
|
||||||
_ => null
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,18 @@
|
|||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Tools.Strings
|
namespace Pilz.Dalamud.Tools.Strings;
|
||||||
|
|
||||||
|
public class StringChange
|
||||||
{
|
{
|
||||||
public class StringChange
|
/// <summary>
|
||||||
{
|
/// The payloads to use for inserting/replacing.
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// The payloads to use for inserting/replacing.
|
public List<Payload> Payloads { get; init; } = [];
|
||||||
/// </summary>
|
|
||||||
public List<Payload> Payloads { get; init; } = new();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines if only one anchor payload should be used, if using anchor payloads.
|
/// Defines if only one anchor payload should be used, if using anchor payloads.
|
||||||
/// With this true the single anchor payload will be used in StringUpdateFactory instead of the anchor payload list.
|
/// With this true the single anchor payload will be used in StringUpdateFactory instead of the anchor payload list.
|
||||||
/// Not needed to be true for the most cases.
|
/// Not needed to be true for the most cases.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ForceUsingSingleAnchorPayload { get; set; } = false;
|
public bool ForceUsingSingleAnchorPayload { get; set; } = false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,32 @@
|
|||||||
using Dalamud.Game.Text.SeStringHandling;
|
namespace Pilz.Dalamud.Tools.Strings;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Tools.Strings
|
public class StringChanges
|
||||||
{
|
{
|
||||||
public class StringChanges
|
private readonly Dictionary<StringPosition, StringChange> changes = [];
|
||||||
|
|
||||||
|
public StringChanges()
|
||||||
{
|
{
|
||||||
private readonly Dictionary<StringPosition, StringChange> changes = new();
|
changes.Add(StringPosition.Before, new StringChange());
|
||||||
|
changes.Add(StringPosition.After, new StringChange());
|
||||||
|
changes.Add(StringPosition.Replace, new StringChange());
|
||||||
|
}
|
||||||
|
|
||||||
public StringChanges()
|
/// <summary>
|
||||||
{
|
/// Gets a change of the position of your choice where you can add your payloads.
|
||||||
changes.Add(StringPosition.Before, new StringChange());
|
/// </summary>
|
||||||
changes.Add(StringPosition.After, new StringChange());
|
/// <param name="position">The position of your choice.</param>
|
||||||
changes.Add(StringPosition.Replace, new StringChange());
|
/// <returns></returns>
|
||||||
}
|
public StringChange GetChange(StringPosition position)
|
||||||
|
{
|
||||||
|
return changes[position];
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a change of the position of your choice where you can add your payloads.
|
/// Checks if there is any string change listed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="position">The position of your choice.</param>
|
/// <returns></returns>
|
||||||
/// <returns></returns>
|
public bool Any()
|
||||||
public StringChange GetChange(StringPosition position)
|
{
|
||||||
{
|
return changes.Sum(n => n.Value.Payloads.Count) != 0;
|
||||||
return changes[position];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if there is any string change listed.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public bool Any()
|
|
||||||
{
|
|
||||||
return changes.Sum(n => n.Value.Payloads.Count) != 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,24 @@
|
|||||||
using Dalamud.Game.ClientState.Objects.Types;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using Dalamud.Game.Text.SeStringHandling;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Tools.Strings
|
namespace Pilz.Dalamud.Tools.Strings;
|
||||||
|
|
||||||
|
public class StringChangesProps
|
||||||
{
|
{
|
||||||
public class StringChangesProps
|
/// <summary>
|
||||||
{
|
/// The string where the changes should be applied.
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// The string where the changes should be applied.
|
public SeString Destination { get; set; }
|
||||||
/// </summary>
|
/// <summary>
|
||||||
public SeString Destination { get; set; }
|
/// The changes that should be applied to the destination.
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// The changes that should be applied to the destination.
|
public StringChanges StringChanges { get; set; } = new();
|
||||||
/// </summary>
|
/// <summary>
|
||||||
public StringChanges StringChanges { get; set; } = new();
|
/// Payloads to use as anchor where the changes should be applied to.
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Payloads to use as anchor where the changes should be applied to.
|
public List<Payload> AnchorPayloads { get; set; } = [];
|
||||||
/// </summary>
|
/// <summary>
|
||||||
public List<Payload> AnchorPayloads { get; set; } = new();
|
/// A single payload to use as anchor where the changes should be applied to.
|
||||||
/// <summary>
|
/// This property will only be used if StringChange.ForceSingleAnchorPayload is true.
|
||||||
/// A single payload to use as anchor where the changes should be applied to.
|
/// </summary>
|
||||||
/// This property will only be used if StringChange.ForceSingleAnchorPayload is true.
|
public Payload AnchorPayload { get; set; }
|
||||||
/// </summary>
|
|
||||||
public Payload AnchorPayload { get; set; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,8 @@
|
|||||||
using System;
|
namespace Pilz.Dalamud.Tools.Strings;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Tools.Strings
|
public enum StringPosition
|
||||||
{
|
{
|
||||||
public enum StringPosition
|
Before,
|
||||||
{
|
After,
|
||||||
Before,
|
Replace
|
||||||
After,
|
|
||||||
Replace
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,132 +1,125 @@
|
|||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||||
using Lumina.Text;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud.Tools.Strings
|
namespace Pilz.Dalamud.Tools.Strings;
|
||||||
|
|
||||||
|
public static class StringUpdateFactory
|
||||||
{
|
{
|
||||||
public static class StringUpdateFactory
|
public static void ApplyStringChanges(StringChangesProps props)
|
||||||
{
|
{
|
||||||
public static void ApplyStringChanges(StringChangesProps props)
|
if (props.StringChanges != null && props.StringChanges.Any())
|
||||||
{
|
{
|
||||||
if (props.StringChanges != null && props.StringChanges.Any())
|
var seString = props.Destination;
|
||||||
|
List<StringPosition> stringPositionsOrdered = GetOrderedStringPositions(props);
|
||||||
|
|
||||||
|
foreach (var stringPosition in stringPositionsOrdered)
|
||||||
{
|
{
|
||||||
var seString = props.Destination;
|
var stringChange = props.StringChanges.GetChange(stringPosition);
|
||||||
List<StringPosition> stringPositionsOrdered = GetOrderedStringPositions(props);
|
if (stringChange != null && stringChange.Payloads.Any())
|
||||||
|
|
||||||
foreach (var stringPosition in stringPositionsOrdered)
|
|
||||||
{
|
{
|
||||||
var stringChange = props.StringChanges.GetChange(stringPosition);
|
AddSpacesBetweenTextPayloads(stringChange.Payloads, stringPosition);
|
||||||
if (stringChange != null && stringChange.Payloads.Any())
|
|
||||||
|
if (stringPosition == StringPosition.Before)
|
||||||
{
|
{
|
||||||
AddSpacesBetweenTextPayloads(stringChange.Payloads, stringPosition);
|
Payload anchorFirst = stringChange.ForceUsingSingleAnchorPayload ? props.AnchorPayload : props.AnchorPayloads?.FirstOrDefault();
|
||||||
|
|
||||||
if (stringPosition == StringPosition.Before)
|
if (anchorFirst != null)
|
||||||
{
|
{
|
||||||
Payload anchorFirst = stringChange.ForceUsingSingleAnchorPayload ? props.AnchorPayload : props.AnchorPayloads?.FirstOrDefault();
|
var anchorPayloadIndex = seString.Payloads.IndexOf(anchorFirst);
|
||||||
|
seString.Payloads.InsertRange(anchorPayloadIndex, stringChange.Payloads);
|
||||||
if (anchorFirst != null)
|
|
||||||
{
|
|
||||||
var anchorPayloadIndex = seString.Payloads.IndexOf(anchorFirst);
|
|
||||||
seString.Payloads.InsertRange(anchorPayloadIndex, stringChange.Payloads);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
seString.Payloads.InsertRange(0, stringChange.Payloads);
|
|
||||||
}
|
}
|
||||||
else if (stringPosition == StringPosition.After)
|
else
|
||||||
{
|
seString.Payloads.InsertRange(0, stringChange.Payloads);
|
||||||
Payload anchorLast = stringChange.ForceUsingSingleAnchorPayload ? props.AnchorPayload : props.AnchorPayloads?.LastOrDefault();
|
}
|
||||||
|
else if (stringPosition == StringPosition.After)
|
||||||
|
{
|
||||||
|
Payload anchorLast = stringChange.ForceUsingSingleAnchorPayload ? props.AnchorPayload : props.AnchorPayloads?.LastOrDefault();
|
||||||
|
|
||||||
if (anchorLast != null)
|
if (anchorLast != null)
|
||||||
{
|
{
|
||||||
var anchorPayloadIndex = seString.Payloads.IndexOf(anchorLast);
|
var anchorPayloadIndex = seString.Payloads.IndexOf(anchorLast);
|
||||||
seString.Payloads.InsertRange(anchorPayloadIndex + 1, stringChange.Payloads);
|
seString.Payloads.InsertRange(anchorPayloadIndex + 1, stringChange.Payloads);
|
||||||
}
|
|
||||||
else
|
|
||||||
seString.Payloads.AddRange(stringChange.Payloads);
|
|
||||||
}
|
}
|
||||||
else if (stringPosition == StringPosition.Replace)
|
else
|
||||||
{
|
seString.Payloads.AddRange(stringChange.Payloads);
|
||||||
Payload anchorReplace = props.AnchorPayload;
|
}
|
||||||
|
else if (stringPosition == StringPosition.Replace)
|
||||||
|
{
|
||||||
|
Payload anchorReplace = props.AnchorPayload;
|
||||||
|
|
||||||
if (anchorReplace != null)
|
if (anchorReplace != null)
|
||||||
{
|
{
|
||||||
var anchorPayloadIndex = seString.Payloads.IndexOf(anchorReplace);
|
var anchorPayloadIndex = seString.Payloads.IndexOf(anchorReplace);
|
||||||
seString.Payloads.InsertRange(anchorPayloadIndex, stringChange.Payloads);
|
seString.Payloads.InsertRange(anchorPayloadIndex, stringChange.Payloads);
|
||||||
seString.Remove(anchorReplace);
|
seString.Remove(anchorReplace);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
seString.Payloads.Clear();
|
seString.Payloads.Clear();
|
||||||
seString.Payloads.AddRange(stringChange.Payloads);
|
seString.Payloads.AddRange(stringChange.Payloads);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private static void AddSpacesBetweenTextPayloads(List<Payload> payloads, StringPosition tagPosition)
|
|
||||||
{
|
private static void AddSpacesBetweenTextPayloads(List<Payload> payloads, StringPosition tagPosition)
|
||||||
if (payloads != null && payloads.Any())
|
{
|
||||||
{
|
if (payloads != null && payloads.Any())
|
||||||
var indicesToInsertSpacesAt = new List<int>();
|
{
|
||||||
var lastTextPayloadIndex = -1;
|
var indicesToInsertSpacesAt = new List<int>();
|
||||||
|
var lastTextPayloadIndex = -1;
|
||||||
static TextPayload getNewTextPayload() => new(" ");
|
|
||||||
|
static TextPayload getNewTextPayload() => new(" ");
|
||||||
foreach (var payload in payloads.Reverse<Payload>())
|
|
||||||
{
|
foreach (var payload in payloads.Reverse<Payload>())
|
||||||
if (payload is IconPayload iconPayload)
|
{
|
||||||
lastTextPayloadIndex = -1;
|
if (payload is IconPayload iconPayload)
|
||||||
else if (payload is TextPayload textPayload)
|
lastTextPayloadIndex = -1;
|
||||||
{
|
else if (payload is TextPayload textPayload)
|
||||||
if (lastTextPayloadIndex != -1)
|
{
|
||||||
indicesToInsertSpacesAt.Add(payloads.IndexOf(textPayload) + 1);
|
if (lastTextPayloadIndex != -1)
|
||||||
lastTextPayloadIndex = payloads.IndexOf(textPayload);
|
indicesToInsertSpacesAt.Add(payloads.IndexOf(textPayload) + 1);
|
||||||
}
|
lastTextPayloadIndex = payloads.IndexOf(textPayload);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
foreach (var indexToInsertSpaceAt in indicesToInsertSpacesAt)
|
|
||||||
payloads.Insert(indexToInsertSpaceAt, getNewTextPayload());
|
foreach (var indexToInsertSpaceAt in indicesToInsertSpacesAt)
|
||||||
|
payloads.Insert(indexToInsertSpaceAt, getNewTextPayload());
|
||||||
// Decide whether to add a space to the end
|
|
||||||
if (tagPosition == StringPosition.Before)
|
// Decide whether to add a space to the end
|
||||||
{
|
if (tagPosition == StringPosition.Before)
|
||||||
var significantPayloads = payloads.Where(payload => payload is TextPayload || payload is IconPayload);
|
{
|
||||||
if (significantPayloads.LastOrDefault() is TextPayload)
|
var significantPayloads = payloads.Where(payload => payload is TextPayload || payload is IconPayload);
|
||||||
payloads.Add(getNewTextPayload());
|
if (significantPayloads.LastOrDefault() is TextPayload)
|
||||||
}
|
payloads.Add(getNewTextPayload());
|
||||||
// Decide whether to add a space to the beginning
|
}
|
||||||
else if (tagPosition == StringPosition.After)
|
// Decide whether to add a space to the beginning
|
||||||
{
|
else if (tagPosition == StringPosition.After)
|
||||||
var significantPayloads = payloads.Where(payload => payload is TextPayload || payload is IconPayload);
|
{
|
||||||
if (significantPayloads.FirstOrDefault() is TextPayload)
|
var significantPayloads = payloads.Where(payload => payload is TextPayload || payload is IconPayload);
|
||||||
payloads.Insert(0, getNewTextPayload());
|
if (significantPayloads.FirstOrDefault() is TextPayload)
|
||||||
}
|
payloads.Insert(0, getNewTextPayload());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private static List<StringPosition> GetOrderedStringPositions(StringChangesProps props)
|
|
||||||
{
|
private static List<StringPosition> GetOrderedStringPositions(StringChangesProps props)
|
||||||
var tagPositionsOrdered = new List<StringPosition>();
|
{
|
||||||
|
var tagPositionsOrdered = new List<StringPosition>();
|
||||||
// If there's no anchor payload, do replaces first so that befores and afters are based on the replaced data
|
|
||||||
if (props.AnchorPayloads == null || !props.AnchorPayloads.Any())
|
// If there's no anchor payload, do replaces first so that befores and afters are based on the replaced data
|
||||||
tagPositionsOrdered.Add(StringPosition.Replace);
|
if (props.AnchorPayloads == null || !props.AnchorPayloads.Any())
|
||||||
|
tagPositionsOrdered.Add(StringPosition.Replace);
|
||||||
tagPositionsOrdered.Add(StringPosition.Before);
|
|
||||||
tagPositionsOrdered.Add(StringPosition.After);
|
tagPositionsOrdered.Add(StringPosition.Before);
|
||||||
|
tagPositionsOrdered.Add(StringPosition.After);
|
||||||
// If there is an anchor payload, do replaces last so that we still know which payload needs to be removed
|
|
||||||
if (props.AnchorPayloads != null && props.AnchorPayloads.Any())
|
// If there is an anchor payload, do replaces last so that we still know which payload needs to be removed
|
||||||
tagPositionsOrdered.Add(StringPosition.Replace);
|
if (props.AnchorPayloads != null && props.AnchorPayloads.Any())
|
||||||
|
tagPositionsOrdered.Add(StringPosition.Replace);
|
||||||
return tagPositionsOrdered;
|
|
||||||
}
|
return tagPositionsOrdered;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
using FFXIVClientStructs.FFXIV.Client.System.Framework;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Pilz.Dalamud.Nameplates.Model;
|
|
||||||
|
|
||||||
namespace Pilz.Dalamud
|
|
||||||
{
|
|
||||||
public class XivApi
|
|
||||||
{
|
|
||||||
private static IntPtr _RaptureAtkModulePtr = IntPtr.Zero;
|
|
||||||
|
|
||||||
public static IntPtr RaptureAtkModulePtr
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_RaptureAtkModulePtr == IntPtr.Zero)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
var framework = Framework.Instance();
|
|
||||||
var uiModule = framework->GetUiModule();
|
|
||||||
|
|
||||||
_RaptureAtkModulePtr = new IntPtr(uiModule->GetRaptureAtkModule());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return _RaptureAtkModulePtr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SafeAddonNameplate GetSafeAddonNamePlate()
|
|
||||||
{
|
|
||||||
return new(PluginServices.PluginInterface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,13 @@
|
|||||||
{
|
{
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"net7.0-windows7.0": {}
|
"net9.0-windows7.0": {
|
||||||
|
"DotNet.ReproducibleBuilds": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[1.2.25, )",
|
||||||
|
"resolved": "1.2.25",
|
||||||
|
"contentHash": "xCXiw7BCxHJ8pF6wPepRUddlh2dlQlbr81gXA72hdk4FLHkKXas7EH/n+fk5UCA/YfMqG1Z6XaPiUjDbUNBUzg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
24
README.md
24
README.md
@@ -8,6 +8,30 @@ At the moment it's far away from being complete or even good. Right now it as so
|
|||||||
Install the latest version of `Pilz.Dalamud` via NuGet Package Manager or NuGet Console:\
|
Install the latest version of `Pilz.Dalamud` via NuGet Package Manager or NuGet Console:\
|
||||||
https://www.nuget.org/packages/Pilz.Dalamud
|
https://www.nuget.org/packages/Pilz.Dalamud
|
||||||
|
|
||||||
|
Or add the alternative package source for slightly quicker updates:\
|
||||||
|
`<add key="Pilz" value="https://git.pilzinsel64.de/api/packages/Pilz.NET/nuget/index.json" />`\
|
||||||
|
|
||||||
|
## Get started
|
||||||
|
|
||||||
|
### Initialize Plugin Services
|
||||||
|
|
||||||
|
To be able to use most features of that lib you must initialize the Plugin Services. The best time to do this is when you initialize your own Plugin Services at your IDalamudPlugin class constructor.
|
||||||
|
|
||||||
|
```cs
|
||||||
|
public Plugin(DalamudPluginInterface pluginInterface)
|
||||||
|
{
|
||||||
|
// Initialize our own Plugin Services if we use them
|
||||||
|
PluginServices.Initialize(pluginInterface);
|
||||||
|
|
||||||
|
// Initialize Plugin Services for `Pilz.Dalamud` because the lib uses them
|
||||||
|
Pilz.Dalamud.PluginServices.Initialize(pluginInterface);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hook into NamePlates
|
||||||
|
|
||||||
|
__**DEPRICATED!** Use the ``INameplate`` service wich is now implemented [within Dalamud](https://github.com/goatcorp/Dalamud/pull/1915). The old Nameplate Addon and the new temporary Nameplate service has been removed since v0.7.0 of this library.__
|
||||||
|
|
||||||
## Contribute
|
## Contribute
|
||||||
|
|
||||||
- Freel free to PR changes or new features/libraries.
|
- Freel free to PR changes or new features/libraries.
|
||||||
|
|||||||
14
deploy-nugets.bat
Normal file
14
deploy-nugets.bat
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
set sourceP="https://git.pilzinsel64.de/api/packages/Pilz.NET/nuget/index.json"
|
||||||
|
set apikeyP=%Gitea_git_pilzinsel64_de%
|
||||||
|
|
||||||
|
set sourceN="https://api.nuget.org/v3/index.json"
|
||||||
|
set apikeyN=%NuGet_ApiKey%
|
||||||
|
|
||||||
|
for %%x in (%*) do (
|
||||||
|
dotnet nuget push "%%x" --source "%sourceP%" --api-key "%apikeyP%" --skip-duplicate
|
||||||
|
dotnet nuget push "%%x" --source "%sourceN%" --api-key "%apikeyN%" --skip-duplicate
|
||||||
|
)
|
||||||
|
|
||||||
|
pause
|
||||||
13
deploy-nugets.sh
Normal file
13
deploy-nugets.sh
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
sourceP="https://git.pilzinsel64.de/api/packages/Pilz.NET/nuget/index.json"
|
||||||
|
apikeyP="$Gitea_git_pilzinsel64_de"
|
||||||
|
|
||||||
|
sourceN="https://api.nuget.org/v3/index.json"
|
||||||
|
apikeyN="$NuGet_ApiKey"
|
||||||
|
|
||||||
|
for pkg in "$@"; do
|
||||||
|
dotnet nuget push "$pkg" --source "$sourceP" --api-key "$apikeyP" --skip-duplicate
|
||||||
|
dotnet nuget push "$pkg" --source "$sourceN" --api-key "$apikeyN" --skip-duplicate
|
||||||
|
done
|
||||||
Reference in New Issue
Block a user