mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +01:00
.
This commit is contained in:
parent
e57538561f
commit
90e451049e
5 changed files with 26 additions and 22 deletions
|
|
@ -77,7 +77,7 @@ public unsafe struct DesignData
|
||||||
fixed (byte* ptr = _equipmentBytes)
|
fixed (byte* ptr = _equipmentBytes)
|
||||||
{
|
{
|
||||||
var armorPtr = (CharacterArmor*)ptr;
|
var armorPtr = (CharacterArmor*)ptr;
|
||||||
return armorPtr[slot is EquipSlot.MainHand ? 10 : 11].ToWeapon(_secondaryMainhand);
|
return slot is EquipSlot.MainHand ? armorPtr[10].ToWeapon(_secondaryMainhand) : armorPtr[11].ToWeapon(_secondaryOffhand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -289,7 +289,7 @@ public unsafe class DebugTab : ITab
|
||||||
? actor.AsCharacter->DrawData.IsWeaponHidden ? "Hidden" : "Visible"
|
? actor.AsCharacter->DrawData.IsWeaponHidden ? "Hidden" : "Visible"
|
||||||
: "No Character");
|
: "No Character");
|
||||||
var text = string.Empty;
|
var text = string.Empty;
|
||||||
// TODO
|
|
||||||
if (!model.IsHuman)
|
if (!model.IsHuman)
|
||||||
{
|
{
|
||||||
text = "No Model";
|
text = "No Model";
|
||||||
|
|
@ -1142,6 +1142,11 @@ public unsafe class DebugTab : ITab
|
||||||
_objectManager.Update();
|
_objectManager.Update();
|
||||||
foreach (var (identifier, actors) in _objectManager)
|
foreach (var (identifier, actors) in _objectManager)
|
||||||
{
|
{
|
||||||
|
if (ImGuiUtil.DrawDisabledButton($"{FontAwesomeIcon.Trash.ToIconString()}##{actors.Label}", new Vector2(ImGui.GetFrameHeight()),
|
||||||
|
string.Empty, !_state.ContainsKey(identifier), true))
|
||||||
|
_state.DeleteState(identifier);
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
using var t = ImRaii.TreeNode(actors.Label);
|
using var t = ImRaii.TreeNode(actors.Label);
|
||||||
if (!t)
|
if (!t)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,10 @@ using Dalamud.Utility.Signatures;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||||
using Glamourer.Events;
|
using Glamourer.Events;
|
||||||
using Glamourer.Interop.Structs;
|
using Glamourer.Interop.Structs;
|
||||||
|
using ImGuiNET;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
using static FFXIVClientStructs.FFXIV.Client.UI.UIModule;
|
||||||
|
|
||||||
namespace Glamourer.Interop;
|
namespace Glamourer.Interop;
|
||||||
|
|
||||||
|
|
@ -69,26 +71,19 @@ public unsafe class WeaponService : IDisposable
|
||||||
switch (slot)
|
switch (slot)
|
||||||
{
|
{
|
||||||
case EquipSlot.MainHand:
|
case EquipSlot.MainHand:
|
||||||
LoadWeaponDetour(&character.AsCharacter->DrawData, 0, weapon.Value, 0, 0, 1, 0);
|
_loadWeaponHook.Original(&character.AsCharacter->DrawData, 0, weapon.Value, 0, 0, 1, 0);
|
||||||
return;
|
return;
|
||||||
case EquipSlot.OffHand:
|
case EquipSlot.OffHand:
|
||||||
LoadWeaponDetour(&character.AsCharacter->DrawData, 1, weapon.Value, 0, 0, 1, 0);
|
_loadWeaponHook.Original(&character.AsCharacter->DrawData, 1, weapon.Value, 0, 0, 1, 0);
|
||||||
return;
|
return;
|
||||||
case EquipSlot.BothHand:
|
case EquipSlot.BothHand:
|
||||||
LoadWeaponDetour(&character.AsCharacter->DrawData, 0, weapon.Value, 0, 0, 1, 0);
|
_loadWeaponHook.Original(&character.AsCharacter->DrawData, 0, weapon.Value, 0, 0, 1, 0);
|
||||||
LoadWeaponDetour(&character.AsCharacter->DrawData, 1, CharacterWeapon.Empty.Value, 0, 0, 1, 0);
|
_loadWeaponHook.Original(&character.AsCharacter->DrawData, 1, CharacterWeapon.Empty.Value, 0, 0, 1, 0);
|
||||||
return;
|
return;
|
||||||
// function can also be called with '2', but does not seem to ever be.
|
// function can also be called with '2', but does not seem to ever be.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load specific Main- and Offhand weapons.
|
|
||||||
public void LoadWeapon(Actor character, CharacterWeapon main, CharacterWeapon off)
|
|
||||||
{
|
|
||||||
LoadWeaponDetour(&character.AsCharacter->DrawData, 0, main.Value, 1, 0, 1, 0);
|
|
||||||
LoadWeaponDetour(&character.AsCharacter->DrawData, 1, off.Value, 1, 0, 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadStain(Actor character, EquipSlot slot, StainId stain)
|
public void LoadStain(Actor character, EquipSlot slot, StainId stain)
|
||||||
{
|
{
|
||||||
var mdl = character.Model;
|
var mdl = character.Model;
|
||||||
|
|
|
||||||
|
|
@ -312,10 +312,11 @@ public class StateListener : IDisposable
|
||||||
return UpdateState.NoChange;
|
return UpdateState.NoChange;
|
||||||
|
|
||||||
// Model ID did change, reload entire state accordingly.
|
// Model ID did change, reload entire state accordingly.
|
||||||
|
// Always use the actor for the base data.
|
||||||
if (modelId == 0)
|
if (modelId == 0)
|
||||||
state.BaseData.LoadNonHuman(modelId, *(Customize*)customizeData, (byte*)equipData);
|
state.BaseData.LoadNonHuman(modelId, *(Customize*)customizeData, (byte*)equipData);
|
||||||
else
|
else
|
||||||
state.BaseData = _manager.FromActor(actor);
|
state.BaseData = _manager.FromActor(actor, false);
|
||||||
|
|
||||||
return UpdateState.Change;
|
return UpdateState.Change;
|
||||||
}
|
}
|
||||||
|
|
@ -334,7 +335,7 @@ public class StateListener : IDisposable
|
||||||
|
|
||||||
// Customize array did not change to stored state.
|
// Customize array did not change to stored state.
|
||||||
if (state.BaseData.Customize.Equals(customize))
|
if (state.BaseData.Customize.Equals(customize))
|
||||||
return UpdateState.NoChange;
|
return UpdateState.NoChange; // TODO: handle wrong base data.
|
||||||
|
|
||||||
// Update customize base state.
|
// Update customize base state.
|
||||||
state.BaseData.Customize.Load(customize);
|
state.BaseData.Customize.Load(customize);
|
||||||
|
|
|
||||||
|
|
@ -75,12 +75,12 @@ public class StateManager : IReadOnlyDictionary<ActorIdentifier, ActorState>
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var designData = FromActor(actor);
|
// Initial Creation, use the actors data for the base data,
|
||||||
// Initial Creation has identical base and model data.
|
// and the draw objects data for the model data (where possible).
|
||||||
state = new ActorState(identifier)
|
state = new ActorState(identifier)
|
||||||
{
|
{
|
||||||
ModelData = designData,
|
ModelData = FromActor(actor, true),
|
||||||
BaseData = designData,
|
BaseData = FromActor(actor, false),
|
||||||
};
|
};
|
||||||
// state.Identifier is owned.
|
// state.Identifier is owned.
|
||||||
_states.Add(state.Identifier, state);
|
_states.Add(state.Identifier, state);
|
||||||
|
|
@ -98,7 +98,7 @@ public class StateManager : IReadOnlyDictionary<ActorIdentifier, ActorState>
|
||||||
/// This uses the draw object if available and where possible,
|
/// This uses the draw object if available and where possible,
|
||||||
/// and the game object where necessary.
|
/// and the game object where necessary.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public unsafe DesignData FromActor(Actor actor)
|
public unsafe DesignData FromActor(Actor actor, bool useModel)
|
||||||
{
|
{
|
||||||
var ret = new DesignData();
|
var ret = new DesignData();
|
||||||
// If the given actor is not a character, just return a default character.
|
// If the given actor is not a character, just return a default character.
|
||||||
|
|
@ -110,7 +110,7 @@ public class StateManager : IReadOnlyDictionary<ActorIdentifier, ActorState>
|
||||||
|
|
||||||
// Model ID is only unambiguously contained in the game object.
|
// Model ID is only unambiguously contained in the game object.
|
||||||
// The draw object only has the object type.
|
// The draw object only has the object type.
|
||||||
// TODO do this right.
|
// TODO reverse search model data to get model id from model.
|
||||||
if (actor.AsCharacter->CharacterData.ModelCharaId != 0)
|
if (actor.AsCharacter->CharacterData.ModelCharaId != 0)
|
||||||
{
|
{
|
||||||
ret.LoadNonHuman((uint)actor.AsCharacter->CharacterData.ModelCharaId, *(Customize*)&actor.AsCharacter->DrawData.CustomizeData,
|
ret.LoadNonHuman((uint)actor.AsCharacter->CharacterData.ModelCharaId, *(Customize*)&actor.AsCharacter->DrawData.CustomizeData,
|
||||||
|
|
@ -127,7 +127,7 @@ public class StateManager : IReadOnlyDictionary<ActorIdentifier, ActorState>
|
||||||
ret.SetHatVisible(!actor.AsCharacter->DrawData.IsHatHidden);
|
ret.SetHatVisible(!actor.AsCharacter->DrawData.IsHatHidden);
|
||||||
|
|
||||||
// Use the draw object if it is a human.
|
// Use the draw object if it is a human.
|
||||||
if (model.IsHuman)
|
if (useModel && model.IsHuman)
|
||||||
{
|
{
|
||||||
// Customize can be obtained from the draw object.
|
// Customize can be obtained from the draw object.
|
||||||
ret.Customize = model.GetCustomize();
|
ret.Customize = model.GetCustomize();
|
||||||
|
|
@ -484,4 +484,7 @@ public class StateManager : IReadOnlyDictionary<ActorIdentifier, ActorState>
|
||||||
_editor.ChangeHatState(data, state.ModelData.IsHatVisible());
|
_editor.ChangeHatState(data, state.ModelData.IsHatVisible());
|
||||||
_editor.ChangeVisor(data, state.ModelData.IsVisorToggled());
|
_editor.ChangeVisor(data, state.ModelData.IsVisorToggled());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DeleteState(ActorIdentifier identifier)
|
||||||
|
=> _states.Remove(identifier);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue