mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2026-02-15 20:17:42 +01:00
,
This commit is contained in:
parent
7463aafa13
commit
27f151c55a
32 changed files with 1744 additions and 151 deletions
|
|
@ -25,7 +25,7 @@ public unsafe class ChangeCustomizeService
|
|||
if (!model.IsHuman)
|
||||
return false;
|
||||
|
||||
Item.Log.Verbose($"[ChangeCustomize] Invoked on 0x{model.Address:X} with {customize}.");
|
||||
Glamourer.Log.Verbose($"[ChangeCustomize] Invoked on 0x{model.Address:X} with {customize}.");
|
||||
return _changeCustomize(model.AsHuman, customize.Data, 1);
|
||||
}
|
||||
|
||||
|
|
|
|||
139
Glamourer/Interop/ObjectManager.cs
Normal file
139
Glamourer/Interop/ObjectManager.cs
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Dalamud.Game;
|
||||
using Dalamud.Game.ClientState;
|
||||
using Dalamud.Game.ClientState.Objects;
|
||||
using Glamourer.Interop.Structs;
|
||||
using Glamourer.Services;
|
||||
using Penumbra.GameData.Actors;
|
||||
|
||||
namespace Glamourer.Interop;
|
||||
|
||||
public class ObjectManager : IReadOnlyDictionary<ActorIdentifier, ActorData>
|
||||
{
|
||||
private readonly Framework _framework;
|
||||
private readonly ClientState _clientState;
|
||||
private readonly ObjectTable _objects;
|
||||
private readonly ActorService _actors;
|
||||
|
||||
public ObjectManager(Framework framework, ClientState clientState, ObjectTable objects, ActorService actors)
|
||||
{
|
||||
_framework = framework;
|
||||
_clientState = clientState;
|
||||
_objects = objects;
|
||||
_actors = actors;
|
||||
}
|
||||
|
||||
public DateTime LastUpdate { get; private set; }
|
||||
|
||||
public bool IsInGPose { get; private set; }
|
||||
public ushort World { get; private set; }
|
||||
|
||||
private readonly Dictionary<ActorIdentifier, ActorData> _identifiers = new(200);
|
||||
|
||||
public IReadOnlyDictionary<ActorIdentifier, ActorData> Identifiers
|
||||
=> _identifiers;
|
||||
|
||||
public void Update()
|
||||
{
|
||||
var lastUpdate = _framework.LastUpdate;
|
||||
if (lastUpdate <= LastUpdate)
|
||||
return;
|
||||
|
||||
LastUpdate = lastUpdate;
|
||||
World = (ushort)(_clientState.LocalPlayer?.CurrentWorld.Id ?? 0u);
|
||||
_identifiers.Clear();
|
||||
|
||||
for (var i = 0; i < (int)ScreenActor.CutsceneStart; ++i)
|
||||
{
|
||||
Actor character = _objects.GetObjectAddress(i);
|
||||
if (character.Identifier(_actors.AwaitedService, out var identifier))
|
||||
HandleIdentifier(identifier, character);
|
||||
}
|
||||
|
||||
for (var i = (int)ScreenActor.CutsceneStart; i < (int)ScreenActor.CutsceneEnd; ++i)
|
||||
{
|
||||
Actor character = _objects.GetObjectAddress(i);
|
||||
if (!character.Valid)
|
||||
break;
|
||||
|
||||
HandleIdentifier(character.GetIdentifier(_actors.AwaitedService), character);
|
||||
}
|
||||
|
||||
void AddSpecial(ScreenActor idx, string label)
|
||||
{
|
||||
Actor actor = _objects.GetObjectAddress((int)idx);
|
||||
if (actor.Identifier(_actors.AwaitedService, out var ident))
|
||||
{
|
||||
var data = new ActorData(actor, label);
|
||||
_identifiers.Add(ident, data);
|
||||
}
|
||||
}
|
||||
|
||||
AddSpecial(ScreenActor.CharacterScreen, "Character Screen Actor");
|
||||
AddSpecial(ScreenActor.ExamineScreen, "Examine Screen Actor");
|
||||
AddSpecial(ScreenActor.FittingRoom, "Fitting Room Actor");
|
||||
AddSpecial(ScreenActor.DyePreview, "Dye Preview Actor");
|
||||
AddSpecial(ScreenActor.Portrait, "Portrait Actor");
|
||||
AddSpecial(ScreenActor.Card6, "Card Actor 6");
|
||||
AddSpecial(ScreenActor.Card7, "Card Actor 7");
|
||||
AddSpecial(ScreenActor.Card8, "Card Actor 8");
|
||||
|
||||
for (var i = (int)ScreenActor.ScreenEnd; i < _objects.Length; ++i)
|
||||
{
|
||||
Actor character = _objects.GetObjectAddress(i);
|
||||
if (character.Identifier(_actors.AwaitedService, out var identifier))
|
||||
HandleIdentifier(identifier, character);
|
||||
}
|
||||
|
||||
var gPose = GPosePlayer;
|
||||
IsInGPose = gPose.Utf8Name.Length > 0;
|
||||
}
|
||||
|
||||
private void HandleIdentifier(ActorIdentifier identifier, Actor character)
|
||||
{
|
||||
if (!character.Model || !identifier.IsValid)
|
||||
return;
|
||||
|
||||
if (!_identifiers.TryGetValue(identifier, out var data))
|
||||
{
|
||||
data = new ActorData(character, identifier.ToString());
|
||||
_identifiers[identifier] = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
data.Objects.Add(character);
|
||||
}
|
||||
}
|
||||
|
||||
public Actor GPosePlayer
|
||||
=> _objects.GetObjectAddress((int)ScreenActor.GPosePlayer);
|
||||
|
||||
public Actor Player
|
||||
=> _objects.GetObjectAddress(0);
|
||||
|
||||
public IEnumerator<KeyValuePair<ActorIdentifier, ActorData>> GetEnumerator()
|
||||
=> Identifiers.GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
=> GetEnumerator();
|
||||
|
||||
public int Count
|
||||
=> Identifiers.Count;
|
||||
|
||||
public bool ContainsKey(ActorIdentifier key)
|
||||
=> Identifiers.ContainsKey(key);
|
||||
|
||||
public bool TryGetValue(ActorIdentifier key, out ActorData value)
|
||||
=> Identifiers.TryGetValue(key, out value);
|
||||
|
||||
public ActorData this[ActorIdentifier key]
|
||||
=> Identifiers[key];
|
||||
|
||||
public IEnumerable<ActorIdentifier> Keys
|
||||
=> Identifiers.Keys;
|
||||
|
||||
public IEnumerable<ActorData> Values
|
||||
=> Identifiers.Values;
|
||||
}
|
||||
|
|
@ -107,11 +107,11 @@ public unsafe class PenumbraService : IDisposable
|
|||
_cutsceneParent = Ipc.GetCutsceneParentIndex.Subscriber(_pluginInterface);
|
||||
_redrawSubscriber = Ipc.RedrawObjectByIndex.Subscriber(_pluginInterface);
|
||||
Available = true;
|
||||
Item.Log.Debug("Glamourer attached to Penumbra.");
|
||||
Glamourer.Log.Debug("Glamourer attached to Penumbra.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Item.Log.Debug($"Could not attach to Penumbra:\n{e}");
|
||||
Glamourer.Log.Debug($"Could not attach to Penumbra:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ public unsafe class PenumbraService : IDisposable
|
|||
if (Available)
|
||||
{
|
||||
Available = false;
|
||||
Item.Log.Debug("Glamourer detached from Penumbra.");
|
||||
Glamourer.Log.Debug("Glamourer detached from Penumbra.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@
|
|||
using System;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.Object;
|
||||
using FFXIVClientStructs.FFXIV.Client.System.String;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
using Penumbra.String;
|
||||
|
||||
namespace Glamourer.Interop.Structs;
|
||||
|
||||
|
|
@ -43,6 +45,9 @@ public readonly unsafe struct Actor : IEquatable<Actor>
|
|||
public ActorIdentifier GetIdentifier(ActorManager actors)
|
||||
=> actors.FromObject(AsObject, out _, true, true, false);
|
||||
|
||||
public ByteString Utf8Name
|
||||
=> Valid ? new ByteString(AsObject->Name) : ByteString.Empty;
|
||||
|
||||
public bool Identifier(ActorManager actors, out ActorIdentifier ident)
|
||||
{
|
||||
if (Valid)
|
||||
|
|
@ -55,6 +60,9 @@ public readonly unsafe struct Actor : IEquatable<Actor>
|
|||
return false;
|
||||
}
|
||||
|
||||
public int Index
|
||||
=> Valid ? AsObject->ObjectIndex : -1;
|
||||
|
||||
public Model Model
|
||||
=> Valid ? AsObject->DrawObject : null;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
namespace Glamourer.Interop.Structs;
|
||||
|
||||
/// <summary>
|
||||
/// A single actor with its label and the list of associated game objects.
|
||||
/// </summary>
|
||||
public readonly struct ActorData
|
||||
{
|
||||
public readonly List<Actor> Objects;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ public class VisorService : IDisposable
|
|||
return false;
|
||||
|
||||
var oldState = GetVisorState(human);
|
||||
Item.Log.Verbose($"[SetVisorState] Invoked manually on 0x{human.Address:X} switching from {oldState} to {on}.");
|
||||
Glamourer.Log.Verbose($"[SetVisorState] Invoked manually on 0x{human.Address:X} switching from {oldState} to {on}.");
|
||||
if (oldState == on)
|
||||
return false;
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ public class VisorService : IDisposable
|
|||
// and also control whether the function should be called at all.
|
||||
Event.Invoke(human, ref on, ref callOriginal);
|
||||
|
||||
Item.Log.Excessive(
|
||||
Glamourer.Log.Excessive(
|
||||
$"[SetVisorState] Invoked from game on 0x{human:X} switching to {on} (original {originalOn}, call original {callOriginal}).");
|
||||
|
||||
if (callOriginal)
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ public unsafe class WeaponService : IDisposable
|
|||
|
||||
// First call the regular function.
|
||||
_loadWeaponHook.Original(drawData, slot, weapon, redrawOnEquality, unk2, skipGameObject, unk4);
|
||||
Item.Log.Information(
|
||||
Glamourer.Log.Excessive(
|
||||
$"Weapon reloaded for 0x{actor.Address:X} with attributes {slot} {weapon:X14}, {redrawOnEquality}, {unk2}, {skipGameObject}, {unk4}");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue