mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2026-02-19 22:17:44 +01:00
deadsa
This commit is contained in:
parent
33c2ed7903
commit
e27a194cc6
47 changed files with 2037 additions and 1167 deletions
|
|
@ -1,7 +1,6 @@
|
|||
using System;
|
||||
using Dalamud.Game.ClientState.Objects.Enums;
|
||||
using Dalamud.Game.ClientState.Objects.Types;
|
||||
using FFXIVClientStructs.FFXIV.Client.System.String;
|
||||
using Glamourer.Customization;
|
||||
using Penumbra.GameData.Actors;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
namespace Glamourer.Interop;
|
||||
|
||||
public static class Offsets
|
||||
{
|
||||
public static class Character
|
||||
{
|
||||
public const int Wetness = 0x1ADA;
|
||||
public const int HatVisible = 0x84E;
|
||||
public const int VisorToggled = 0x84F;
|
||||
public const int WeaponHidden1 = 0x84F;
|
||||
public const int WeaponHidden2 = 0x72C;
|
||||
public const int Alpha = 0x19E0;
|
||||
|
||||
public static class Flags
|
||||
{
|
||||
public const byte IsHatHidden = 0x01;
|
||||
public const byte IsVisorToggled = 0x08;
|
||||
public const byte IsWet = 0x80;
|
||||
public const byte IsWeaponHidden1 = 0x01;
|
||||
public const byte IsWeaponHidden2 = 0x02;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,8 @@ public unsafe partial class RedrawManager
|
|||
[Signature("E8 ?? ?? ?? ?? 41 0F B6 C5 66 41 89 86")]
|
||||
private readonly ChangeCustomizeDelegate _changeCustomize = null!;
|
||||
|
||||
|
||||
|
||||
public bool UpdateCustomize(Actor actor, Customize customize)
|
||||
{
|
||||
if (!actor.Valid || !actor.DrawObject.Valid)
|
||||
|
|
@ -43,10 +45,11 @@ public unsafe partial class RedrawManager
|
|||
return;
|
||||
|
||||
var flags = &data->CharacterBase.UnkFlags_01;
|
||||
var state = (*flags & 0x40) != 0;
|
||||
var state = (*flags & Offsets.DrawObjectVisorStateFlag) != 0;
|
||||
if (state == on)
|
||||
return;
|
||||
|
||||
*flags = (byte)((on ? *flags | 0x40 : *flags & 0xBF) | 0x80);
|
||||
var newFlag = (byte)(on ? *flags | Offsets.DrawObjectVisorStateFlag : *flags & ~Offsets.DrawObjectVisorStateFlag);
|
||||
*flags = (byte) (newFlag | Offsets.DrawObjectVisorToggleFlag);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
using System;
|
||||
using Dalamud.Hooking;
|
||||
using Dalamud.Logging;
|
||||
using Dalamud.Utility.Signatures;
|
||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||
using Glamourer.Designs;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
|
|
@ -10,59 +9,76 @@ namespace Glamourer.Interop;
|
|||
|
||||
public unsafe partial class RedrawManager
|
||||
{
|
||||
public delegate ulong FlagSlotForUpdateDelegate(Human* drawObject, uint slot, CharacterArmor* data);
|
||||
private delegate ulong FlagSlotForUpdateDelegate(nint drawObject, uint slot, CharacterArmor* data);
|
||||
|
||||
// This gets called when one of the ten equip items of an existing draw object gets changed.
|
||||
[Signature("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 8B DA 49 8B F0 48 8B F9 83 FA 0A", DetourName = nameof(FlagSlotForUpdateDetour))]
|
||||
[Signature(Sigs.FlagSlotForUpdate, DetourName = nameof(FlagSlotForUpdateDetour))]
|
||||
private readonly Hook<FlagSlotForUpdateDelegate> _flagSlotForUpdateHook = null!;
|
||||
|
||||
private ulong FlagSlotForUpdateDetour(Human* drawObject, uint slotIdx, CharacterArmor* data)
|
||||
public void UpdateSlot(DrawObject drawObject, EquipSlot slot, CharacterArmor data)
|
||||
=> FlagSlotForUpdateDetourBase(drawObject.Address, slot.ToIndex(), &data, true);
|
||||
|
||||
public void UpdateStain(DrawObject drawObject, EquipSlot slot, StainId stain)
|
||||
{
|
||||
var armor = drawObject.Equip[slot] with { Stain = stain};
|
||||
UpdateSlot(drawObject, slot, armor);
|
||||
}
|
||||
|
||||
private ulong FlagSlotForUpdateDetour(nint drawObject, uint slotIdx, CharacterArmor* data)
|
||||
=> FlagSlotForUpdateDetourBase(drawObject, slotIdx, data, false);
|
||||
|
||||
private ulong FlagSlotForUpdateDetourBase(nint drawObject, uint slotIdx, CharacterArmor* data, bool manual)
|
||||
{
|
||||
var slot = slotIdx.ToEquipSlot();
|
||||
try
|
||||
{
|
||||
var actor = Glamourer.Penumbra.GameObjectFromDrawObject((IntPtr)drawObject);
|
||||
var identifier = actor.GetIdentifier();
|
||||
|
||||
if (_fixedDesigns.TryGetDesign(identifier, out var save))
|
||||
{
|
||||
PluginLog.Information($"Loaded {slot} from fixed design for {identifier}.");
|
||||
(var replaced, *data) =
|
||||
Glamourer.RestrictedGear.ResolveRestricted(save.Equipment[slot], slot, (Race)drawObject->Race, (Gender)drawObject->Sex);
|
||||
}
|
||||
else if (_currentManipulations.TryGetDesign(identifier, out var save2))
|
||||
{
|
||||
PluginLog.Information($"Updated {slot} from current designs for {identifier}.");
|
||||
(var replaced, *data) =
|
||||
Glamourer.RestrictedGear.ResolveRestricted(*data, slot, (Race)drawObject->Race, (Gender)(drawObject->Sex + 1));
|
||||
save2.Data.Equipment[slot] = *data;
|
||||
}
|
||||
var slot = slotIdx.ToEquipSlot();
|
||||
Glamourer.Log.Verbose(
|
||||
$"Flagged slot {slot} of 0x{(ulong)drawObject:X} for update with {data->Set.Value}-{data->Variant} (Stain {data->Stain.Value}).");
|
||||
HandleEquipUpdate(drawObject, slot, ref *data, manual);
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginLog.Error($"Error on loading new gear:\n{e}");
|
||||
Glamourer.Log.Error($"Error invoking SlotUpdate:\n{ex}");
|
||||
}
|
||||
|
||||
return _flagSlotForUpdateHook.Original(drawObject, slotIdx, data);
|
||||
|
||||
//try
|
||||
//{
|
||||
// var actor = Glamourer.Penumbra.GameObjectFromDrawObject((IntPtr)drawObject);
|
||||
// var identifier = actor.GetIdentifier();
|
||||
//
|
||||
// if (_fixedDesigns.TryGetDesign(identifier, out var design))
|
||||
// {
|
||||
// PluginLog.Information($"Loaded {slot} from fixed design for {identifier}.");
|
||||
// (var replaced, *data) =
|
||||
// Glamourer.Items.RestrictedGear.ResolveRestricted(design.Armor(slot).Model, slot, (Race)drawObject->Race, (Gender)drawObject->Sex);
|
||||
// }
|
||||
// else if (_currentManipulations.TryGetDesign(identifier, out var save2))
|
||||
// {
|
||||
// PluginLog.Information($"Updated {slot} from current designs for {identifier}.");
|
||||
// (var replaced, *data) =
|
||||
// Glamourer.Items.RestrictedGear.ResolveRestricted(*data, slot, (Race)drawObject->Race, (Gender)(drawObject->Sex + 1));
|
||||
// save2.Data.Equipment[slot] = *data;
|
||||
// }
|
||||
//}
|
||||
//catch (Exception e)
|
||||
//{
|
||||
// PluginLog.Error($"Error on loading new gear:\n{e}");
|
||||
//}
|
||||
//
|
||||
//return _flagSlotForUpdateHook.Original(drawObject, slotIdx, data);
|
||||
}
|
||||
|
||||
public bool ChangeEquip(DrawObject drawObject, uint slotIdx, CharacterArmor data)
|
||||
private void HandleEquipUpdate(nint drawObject, EquipSlot slot, ref CharacterArmor data, bool manual)
|
||||
{
|
||||
if (!drawObject)
|
||||
return false;
|
||||
var actor = Glamourer.Penumbra.GameObjectFromDrawObject(drawObject);
|
||||
var identifier = actor.GetIdentifier();
|
||||
|
||||
if (slotIdx > 9)
|
||||
return false;
|
||||
if (!_currentManipulations.TryGetDesign(identifier, out var design))
|
||||
return;
|
||||
|
||||
return FlagSlotForUpdateDetour(drawObject.Pointer, slotIdx, &data) != 0;
|
||||
var flag = slot.ToFlag();
|
||||
var stainFlag = slot.ToStainFlag();
|
||||
}
|
||||
|
||||
public bool ChangeEquip(Actor actor, EquipSlot slot, CharacterArmor data)
|
||||
=> actor && ChangeEquip(actor.DrawObject, slot.ToIndex(), data);
|
||||
|
||||
public bool ChangeEquip(DrawObject drawObject, EquipSlot slot, CharacterArmor data)
|
||||
=> ChangeEquip(drawObject, slot.ToIndex(), data);
|
||||
|
||||
public bool ChangeEquip(Actor actor, uint slotIdx, CharacterArmor data)
|
||||
=> actor && ChangeEquip(actor.DrawObject, slotIdx, data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ public unsafe partial class RedrawManager
|
|||
PluginLog.Information($"Loaded weapon from fixed design for {identifier}.");
|
||||
weapon = slot switch
|
||||
{
|
||||
0 => save.MainHand.Value,
|
||||
1 => save.OffHand.Value,
|
||||
0 => save.WeaponMain.Model.Value,
|
||||
1 => save.WeaponOff.Model.Value,
|
||||
_ => weapon,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,27 +2,40 @@
|
|||
using Dalamud.Hooking;
|
||||
using Dalamud.Logging;
|
||||
using Dalamud.Utility.Signatures;
|
||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||
using Glamourer.Customization;
|
||||
using Glamourer.State;
|
||||
using Glamourer.Structs;
|
||||
using Penumbra.GameData.Data;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
using CustomizeData = Penumbra.GameData.Structs.CustomizeData;
|
||||
|
||||
namespace Glamourer.Interop;
|
||||
|
||||
public class DesignBaseValidator
|
||||
{
|
||||
private readonly CustomizationManager _manager;
|
||||
private readonly RestrictedGear _restrictedGear;
|
||||
|
||||
public DesignBaseValidator(CustomizationManager manager, RestrictedGear restrictedGear)
|
||||
{
|
||||
_manager = manager;
|
||||
_restrictedGear = restrictedGear;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public unsafe partial class RedrawManager
|
||||
{
|
||||
private delegate void ChangeJobDelegate(IntPtr data, uint job);
|
||||
|
||||
[Signature("88 51 ?? 44 3B CA", DetourName = nameof(ChangeJobDetour))]
|
||||
[Signature(Sigs.ChangeJob, DetourName = nameof(ChangeJobDetour))]
|
||||
private readonly Hook<ChangeJobDelegate> _changeJobHook = null!;
|
||||
|
||||
private void ChangeJobDetour(IntPtr data, uint job)
|
||||
{
|
||||
_changeJobHook.Original(data, job);
|
||||
JobChanged?.Invoke(data - 0x1A8, GameData.Jobs(Dalamud.GameData)[(byte)job]);
|
||||
JobChanged?.Invoke(data - Offsets.Character.ClassJobContainer, GameData.Jobs(Dalamud.GameData)[(byte)job]);
|
||||
}
|
||||
|
||||
public event Action<Actor, Job>? JobChanged;
|
||||
|
|
@ -70,18 +83,18 @@ public unsafe partial class RedrawManager : IDisposable
|
|||
// Apply customization if they correspond and there is customization to apply.
|
||||
var gameObjectCustomize = new Customize((CustomizeData*)actor.Pointer->CustomizeData);
|
||||
if (gameObjectCustomize.Equals(customize))
|
||||
customize.Load(save!.Data.Customize);
|
||||
customize.Load(save!.Customize());
|
||||
|
||||
// Compare game object equip data against draw object equip data for transformations.
|
||||
// Apply each piece of equip that should be applied if they correspond.
|
||||
var gameObjectEquip = new CharacterEquip((CharacterArmor*)actor.Pointer->EquipSlotData);
|
||||
if (gameObjectEquip.Equals(equip))
|
||||
{
|
||||
var saveEquip = save!.Data.Equipment;
|
||||
var saveEquip = save!.Equipment();
|
||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||
{
|
||||
(_, equip[slot]) =
|
||||
Glamourer.RestrictedGear.ResolveRestricted(saveEquip[slot], slot, customize.Race, customize.Gender);
|
||||
Glamourer.Items.RestrictedGear.ResolveRestricted(saveEquip[slot], slot, customize.Race, customize.Gender);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue