This commit is contained in:
Ottermandias 2023-06-28 16:53:19 +02:00
parent e57538561f
commit 90e451049e
5 changed files with 26 additions and 22 deletions

View file

@ -77,7 +77,7 @@ public unsafe struct DesignData
fixed (byte* ptr = _equipmentBytes)
{
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);
}
}

View file

@ -289,7 +289,7 @@ public unsafe class DebugTab : ITab
? actor.AsCharacter->DrawData.IsWeaponHidden ? "Hidden" : "Visible"
: "No Character");
var text = string.Empty;
// TODO
if (!model.IsHuman)
{
text = "No Model";
@ -1142,6 +1142,11 @@ public unsafe class DebugTab : ITab
_objectManager.Update();
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);
if (!t)
continue;

View file

@ -4,8 +4,10 @@ using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using Glamourer.Events;
using Glamourer.Interop.Structs;
using ImGuiNET;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs;
using static FFXIVClientStructs.FFXIV.Client.UI.UIModule;
namespace Glamourer.Interop;
@ -69,26 +71,19 @@ public unsafe class WeaponService : IDisposable
switch (slot)
{
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;
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;
case EquipSlot.BothHand:
LoadWeaponDetour(&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, 0, weapon.Value, 0, 0, 1, 0);
_loadWeaponHook.Original(&character.AsCharacter->DrawData, 1, CharacterWeapon.Empty.Value, 0, 0, 1, 0);
return;
// 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)
{
var mdl = character.Model;

View file

@ -312,10 +312,11 @@ public class StateListener : IDisposable
return UpdateState.NoChange;
// Model ID did change, reload entire state accordingly.
// Always use the actor for the base data.
if (modelId == 0)
state.BaseData.LoadNonHuman(modelId, *(Customize*)customizeData, (byte*)equipData);
else
state.BaseData = _manager.FromActor(actor);
state.BaseData = _manager.FromActor(actor, false);
return UpdateState.Change;
}
@ -334,7 +335,7 @@ public class StateListener : IDisposable
// Customize array did not change to stored state.
if (state.BaseData.Customize.Equals(customize))
return UpdateState.NoChange;
return UpdateState.NoChange; // TODO: handle wrong base data.
// Update customize base state.
state.BaseData.Customize.Load(customize);

View file

@ -75,12 +75,12 @@ public class StateManager : IReadOnlyDictionary<ActorIdentifier, ActorState>
try
{
var designData = FromActor(actor);
// Initial Creation has identical base and model data.
// Initial Creation, use the actors data for the base data,
// and the draw objects data for the model data (where possible).
state = new ActorState(identifier)
{
ModelData = designData,
BaseData = designData,
ModelData = FromActor(actor, true),
BaseData = FromActor(actor, false),
};
// state.Identifier is owned.
_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,
/// and the game object where necessary.
/// </summary>
public unsafe DesignData FromActor(Actor actor)
public unsafe DesignData FromActor(Actor actor, bool useModel)
{
var ret = new DesignData();
// 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.
// 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)
{
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);
// Use the draw object if it is a human.
if (model.IsHuman)
if (useModel && model.IsHuman)
{
// Customize can be obtained from the draw object.
ret.Customize = model.GetCustomize();
@ -484,4 +484,7 @@ public class StateManager : IReadOnlyDictionary<ActorIdentifier, ActorState>
_editor.ChangeHatState(data, state.ModelData.IsHatVisible());
_editor.ChangeVisor(data, state.ModelData.IsVisorToggled());
}
public void DeleteState(ActorIdentifier identifier)
=> _states.Remove(identifier);
}