feat: add housing location
This commit is contained in:
parent
5e9321cc86
commit
f9db679957
|
@ -0,0 +1,56 @@
|
|||
using System;
|
||||
using Dalamud.Game;
|
||||
|
||||
namespace XivCommon.Functions.Housing {
|
||||
/// <summary>
|
||||
/// The class containing housing functionality
|
||||
/// </summary>
|
||||
public class Housing {
|
||||
private static class Signatures {
|
||||
internal const string HousingPointer = "48 8B 05 ?? ?? ?? ?? 48 83 78 ?? ?? 74 16 48 8D 8F ?? ?? ?? ?? 66 89 5C 24 ?? 48 8D 54 24 ?? E8 ?? ?? ?? ?? 48 8B 7C 24";
|
||||
}
|
||||
|
||||
private IntPtr HousingPointer { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the raw struct containing information about the player's current location in a housing ward.
|
||||
///
|
||||
/// <returns>struct if player is in a housing ward, null otherwise</returns>
|
||||
/// </summary>
|
||||
// Updated: 5.55
|
||||
// 48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC 20 49 8B 00 (ward?)
|
||||
public unsafe RawHousingLocation? RawLocation {
|
||||
get {
|
||||
if (this.HousingPointer == IntPtr.Zero) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var loc = Util.FollowPointerChain(this.HousingPointer, new[] { 0, 0 });
|
||||
if (loc == IntPtr.Zero) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var locPtr = (RawHousingLocation*) (loc + 0x96a0);
|
||||
return *locPtr;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets process information about the player's current location in a housing ward.
|
||||
///
|
||||
/// <returns>information class if player is in a housing ward, null otherwise</returns>
|
||||
/// </summary>
|
||||
public HousingLocation? Location {
|
||||
get {
|
||||
var loc = this.RawLocation;
|
||||
return loc == null ? null : new HousingLocation(loc.Value);
|
||||
}
|
||||
}
|
||||
|
||||
internal Housing(SigScanner scanner) {
|
||||
if (scanner.TryGetStaticAddressFromSig(Signatures.HousingPointer, out var ptr)) {
|
||||
this.HousingPointer = ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
namespace XivCommon.Functions.Housing {
|
||||
/// <summary>
|
||||
/// Information about a player's current location in a housing ward.
|
||||
/// </summary>
|
||||
public class HousingLocation {
|
||||
/// <summary>
|
||||
/// The housing ward that the player is in.
|
||||
/// </summary>
|
||||
public ushort Ward;
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// The yard that the player is in.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This is the same as plot number but indicates that the player is in
|
||||
/// the exterior area (the yard) of that plot.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public ushort? Yard;
|
||||
/// <summary>
|
||||
/// The plot that the player is in.
|
||||
/// </summary>
|
||||
public ushort? Plot;
|
||||
/// <summary>
|
||||
/// The apartment wing (1 or 2 for normal or subdivision) that the
|
||||
/// player is in.
|
||||
/// </summary>
|
||||
public ushort? ApartmentWing;
|
||||
/// <summary>
|
||||
/// The apartment that the player is in.
|
||||
/// </summary>
|
||||
public ushort? Apartment;
|
||||
|
||||
internal HousingLocation(RawHousingLocation loc) {
|
||||
var ward = loc.CurrentWard;
|
||||
|
||||
if ((loc.CurrentPlot & 0x80) > 0) {
|
||||
// the struct is in apartment mode
|
||||
this.ApartmentWing = (ushort?) ((loc.CurrentPlot & ~0x80) + 1);
|
||||
this.Apartment = (ushort?) (ward >> 6);
|
||||
this.Ward = (ushort) ((ward & 0x3F) + 1);
|
||||
if (this.Apartment == 0) {
|
||||
this.Apartment = null;
|
||||
}
|
||||
} else if (loc.InsideIndicator == 0) {
|
||||
// inside a plot
|
||||
this.Plot = (ushort?) (loc.CurrentPlot + 1);
|
||||
} else if (loc.CurrentYard != 0xFF) {
|
||||
// not inside a plot
|
||||
// yard is 0xFF when not in one
|
||||
this.Yard = (ushort?) (loc.CurrentYard + 1);
|
||||
}
|
||||
|
||||
if (this.Ward == 0) {
|
||||
this.Ward = (ushort) (ward + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace XivCommon.Functions.Housing {
|
||||
/// <summary>
|
||||
/// Information about the player's current location in a housing ward as
|
||||
/// kept by the game's internal structures.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public readonly struct RawHousingLocation {
|
||||
/// <summary>
|
||||
/// The zero-indexed plot number that the player is in.
|
||||
///
|
||||
/// <para>
|
||||
/// Contains apartment data when inside an apartment building.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public readonly ushort CurrentPlot; // a0 -> a2
|
||||
/// <summary>
|
||||
/// The zero-indexed ward number that the player is in.
|
||||
///
|
||||
/// <para>
|
||||
/// Contains apartment data when inside an apartment building.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public readonly ushort CurrentWard; // a2 -> a4
|
||||
private readonly uint unknownBytes1; // a4 -> a8
|
||||
/// <summary>
|
||||
/// The zero-indexed yard number that the player is in.
|
||||
///
|
||||
/// <para>
|
||||
/// Is <c>0xFF</c> when not in a yard.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public readonly byte CurrentYard; // a8 -> a9
|
||||
private readonly byte unknownBytes2; // a9 -> aa
|
||||
/// <summary>
|
||||
/// A byte that is zero when the player is inside a plot.
|
||||
/// </summary>
|
||||
public readonly byte InsideIndicator; // aa -> ab
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ using FFXIVClientStructs.FFXIV.Component.GUI;
|
|||
using XivCommon.Functions;
|
||||
using XivCommon.Functions.ContextMenu;
|
||||
using XivCommon.Functions.FriendList;
|
||||
using XivCommon.Functions.Housing;
|
||||
using XivCommon.Functions.NamePlates;
|
||||
using XivCommon.Functions.Tooltips;
|
||||
using Framework = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework;
|
||||
|
@ -83,6 +84,11 @@ namespace XivCommon {
|
|||
/// Journal functions
|
||||
/// </summary>
|
||||
public Journal Journal { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Housing functions
|
||||
/// </summary>
|
||||
public Housing Housing { get; }
|
||||
|
||||
internal GameFunctions(Hooks hooks) {
|
||||
this.Framework = Util.GetService<Dalamud.Game.Framework>();
|
||||
|
@ -106,6 +112,7 @@ namespace XivCommon {
|
|||
this.DutyFinder = new DutyFinder(this, scanner);
|
||||
this.Journal = new Journal(this, scanner);
|
||||
this.FriendList = new FriendList(this);
|
||||
this.Housing = new Housing(scanner);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
|
@ -44,5 +44,20 @@ namespace XivCommon {
|
|||
var get = service.GetMethod("Get", BindingFlags.Public | BindingFlags.Static)!;
|
||||
return (T) get.Invoke(null, null)!;
|
||||
}
|
||||
|
||||
internal static unsafe IntPtr FollowPointerChain(IntPtr start, IEnumerable<int> offsets) {
|
||||
if (start == IntPtr.Zero) {
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
foreach (var offset in offsets) {
|
||||
start = *(IntPtr*) (start + offset);
|
||||
if (start == IntPtr.Zero) {
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue