From 11261e9e0791f4d3ebfa4aa8573c1ecc17e3c62b Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Thu, 4 Jul 2024 09:32:50 +0100 Subject: [PATCH 01/23] Update Dalamud API + CS --- Ktisis/Camera/CameraService.cs | 9 ++--- Ktisis/Camera/KtisisCamera.cs | 2 +- Ktisis/Configuration.cs | 1 + Ktisis/Data/Excel/Item.cs | 2 +- .../Converters/JsonFileConverter.cs | 4 +- Ktisis/Env/EnvService.cs | 11 +++--- Ktisis/Env/WeatherInfo.cs | 2 +- Ktisis/Events/EventManager.cs | 7 ++-- Ktisis/History/ActorBone.cs | 8 ++-- Ktisis/Interface/Components/ActorsList.cs | 4 +- .../Interface/Components/AnimationControls.cs | 4 +- Ktisis/Interface/Components/TransformTable.cs | 3 +- .../Windows/ActorEdit/EditCustomize.cs | 9 ++--- .../Interface/Windows/ActorEdit/EditEquip.cs | 11 ++---- Ktisis/Interface/Windows/ConfigGui.cs | 4 +- Ktisis/Interface/Windows/References.cs | 5 +-- .../Windows/Workspace/Tabs/ActorTab.cs | 2 +- .../Windows/Workspace/Tabs/CameraTab.cs | 2 +- .../Windows/Workspace/Tabs/PoseTab.cs | 2 +- .../Windows/Workspace/Tabs/WorldTab.cs | 2 +- .../Interface/Windows/Workspace/Workspace.cs | 2 +- Ktisis/Interop/Alloc.cs | 6 +-- Ktisis/Interop/Hooks/CameraHooks.cs | 4 +- Ktisis/Interop/Hooks/EventsHooks.cs | 2 +- Ktisis/Interop/Hooks/PoseHooks.cs | 7 ++-- Ktisis/Ktisis.cs | 12 ++++-- Ktisis/Logger.cs | 14 +++---- Ktisis/Services.cs | 4 +- Ktisis/Structs/Actor/Actor.cs | 8 ++-- Ktisis/Structs/Actor/ActorModel.cs | 3 +- .../Structs/Actor/Equip/SetSources/GearSet.cs | 37 +++++++++---------- Ktisis/Structs/Actor/Weapon.cs | 2 +- Ktisis/Structs/Bones/Bone.cs | 10 ++--- Ktisis/Structs/Extensions/Havok.cs | 6 ++- .../Structs/FFXIV/MiragePrismMiragePlate.cs | 3 +- Ktisis/Structs/Poses/Transform.cs | 2 +- Ktisis/Util/NpcImportService.cs | 2 +- 37 files changed, 109 insertions(+), 109 deletions(-) diff --git a/Ktisis/Camera/CameraService.cs b/Ktisis/Camera/CameraService.cs index fd5cac86e..d9834f5bf 100644 --- a/Ktisis/Camera/CameraService.cs +++ b/Ktisis/Camera/CameraService.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Collections.ObjectModel; -using Dalamud.Logging; using Dalamud.Game.ClientState.Objects.Types; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; @@ -29,7 +28,7 @@ internal static class CameraService { var camera = GetCameraByAddress((nint)active); if (camera == null && Override != null) { - PluginLog.Warning("Lost track of active camera! Attempting to reset."); + Ktisis.Log.Warning("Lost track of active camera! Attempting to reset."); Reset(); camera = GetCameraByAddress((nint)Services.Camera->Camera); } @@ -83,7 +82,7 @@ internal unsafe static void RemoveCamera(KtisisCamera cam) { return pos; } - internal static GameObject? GetTargetLock(nint addr) { + internal static IGameObject? GetTargetLock(nint addr) { if (!Ktisis.IsInGPose || GetCameraByAddress(addr) is not KtisisCamera camera) return null; @@ -141,7 +140,7 @@ internal unsafe static void Reset() { private unsafe static void SetCamera(GameCamera* camera) { if (camera == null) return; var mgr = CameraManager.Instance(); - mgr->CameraArraySpan[0] = &camera->CameraBase.SceneCamera; + mgr->Cameras[0] = &camera->CameraBase.SceneCamera; } // Overrides @@ -217,7 +216,7 @@ private unsafe static void PrepareCameraList() { } private unsafe static void DisposeCameras() { - PluginLog.Debug("Disposing cameras..."); + Ktisis.Log.Debug("Disposing cameras..."); if (Override != null) Reset(); foreach (var cam in Cameras) diff --git a/Ktisis/Camera/KtisisCamera.cs b/Ktisis/Camera/KtisisCamera.cs index 252e88589..6d54b3b7b 100644 --- a/Ktisis/Camera/KtisisCamera.cs +++ b/Ktisis/Camera/KtisisCamera.cs @@ -72,7 +72,7 @@ public unsafe static KtisisCamera Spawn(GameCamera* clone = null) { public void SetPositionLock(Vector3? pos) => CameraEdit.Position = pos; public void SetOffset(Vector3? off) => CameraEdit.Offset = off; - internal GameObject? GetOrbitTarget() { + internal IGameObject? GetOrbitTarget() { if (!Ktisis.IsInGPose) return null; return CameraEdit.Orbit != null ? Services.ObjectTable.FirstOrDefault( actor => actor.ObjectIndex == CameraEdit.Orbit diff --git a/Ktisis/Configuration.cs b/Ktisis/Configuration.cs index 4b52cba4f..4fc214b77 100644 --- a/Ktisis/Configuration.cs +++ b/Ktisis/Configuration.cs @@ -8,6 +8,7 @@ using Dalamud; using Dalamud.Configuration; +using Dalamud.Game; using Dalamud.Game.ClientState.Keys; using Ktisis.Interface; diff --git a/Ktisis/Data/Excel/Item.cs b/Ktisis/Data/Excel/Item.cs index 17aa815c7..1582e99ac 100644 --- a/Ktisis/Data/Excel/Item.cs +++ b/Ktisis/Data/Excel/Item.cs @@ -37,7 +37,7 @@ public ItemModel(ulong var, bool isWep = false) { [Sheet("Item")] public class Item : ExcelRow { public string Name { get; set; } = ""; - public ushort Icon { get; set; } + public int Icon { get; set; } public LazyRow EquipSlotCategory { get; set; } = null!; diff --git a/Ktisis/Data/Serialization/Converters/JsonFileConverter.cs b/Ktisis/Data/Serialization/Converters/JsonFileConverter.cs index 1d69f2c0f..ce8040427 100644 --- a/Ktisis/Data/Serialization/Converters/JsonFileConverter.cs +++ b/Ktisis/Data/Serialization/Converters/JsonFileConverter.cs @@ -3,8 +3,6 @@ using System.Text.Json; using System.Text.Json.Serialization; -using Dalamud.Logging; - using Ktisis.Data.Files; namespace Ktisis.Data.Serialization.Converters { @@ -27,7 +25,7 @@ public class JsonFileConverter : JsonConverter { var value = jsonValue.Deserialize(prop.PropertyType, options); if (value != null) prop.SetValue(result, value); } catch { - PluginLog.Warning($"Failed to parse {prop.PropertyType.Name} value '{prop.Name}' (received {jsonValue.ValueKind} instead)"); + Ktisis.Log.Warning($"Failed to parse {prop.PropertyType.Name} value '{prop.Name}' (received {jsonValue.ValueKind} instead)"); } } diff --git a/Ktisis/Env/EnvService.cs b/Ktisis/Env/EnvService.cs index 19f349ce4..a26b9a782 100644 --- a/Ktisis/Env/EnvService.cs +++ b/Ktisis/Env/EnvService.cs @@ -3,8 +3,7 @@ using System.Threading; using System.Threading.Tasks; -using Dalamud.Interface.Internal; -using Dalamud.Logging; +using Dalamud.Interface.Textures.TextureWraps; using FFXIVClientStructs.FFXIV.Client.Graphics.Environment; @@ -56,7 +55,7 @@ public static void GetSkyImage(uint sky) { CurSky = sky; GetSkyboxTex(CurSky).ContinueWith(result => { if (result.Exception != null) { - PluginLog.Error(result.Exception.ToString()); + Ktisis.Log.Error(result.Exception.ToString()); return; } @@ -69,8 +68,8 @@ public static void GetSkyImage(uint sky) { private static async Task GetSkyboxTex(uint skyId) { await Task.Yield(); - PluginLog.Verbose($"Retrieving skybox texture: {skyId:000}"); - return Services.Textures.GetTextureFromGame($"bgcommon/nature/sky/texture/sky_{skyId:000}.tex"); + Ktisis.Log.Verbose($"Retrieving skybox texture: {skyId:000}"); + return Services.Textures.GetFromGame($"bgcommon/nature/sky/texture/sky_{skyId:000}.tex").GetWrapOrEmpty(); } public unsafe static byte[] GetEnvWeatherIds() { @@ -96,7 +95,7 @@ public static async Task> GetWeatherIcons(IEnumerableModel->Transform : bone.AccessModelSpace(PropagateOrNot.DontPropagate); + hkQsTransformf* boneTransform = bone is null ? &actor->Model->Transform : bone.AccessModelSpace(hkaPose.PropagateOrNot.DontPropagate); OnTransformationMatrixChange(state); } diff --git a/Ktisis/History/ActorBone.cs b/Ktisis/History/ActorBone.cs index 7bf36b4d1..6de7ae18e 100644 --- a/Ktisis/History/ActorBone.cs +++ b/Ktisis/History/ActorBone.cs @@ -1,11 +1,11 @@ using System.Numerics; +using FFXIVClientStructs.Havok.Animation.Rig; + using Ktisis.Structs; using Ktisis.Structs.Actor; using Ktisis.Structs.Bones; -using static FFXIVClientStructs.Havok.hkaPose; - namespace Ktisis.History { public class ActorBone : HistoryItem { private Bone? Bone { get; set; } // This should never have been introduced here. @@ -58,7 +58,7 @@ public unsafe override void Update(bool undo) { var bone = model->Skeleton->GetBone(historyBone.Partial, historyBone.Index); var boneName = bone.HkaBone.Name.String ?? ""; - var boneTransform = bone.AccessModelSpace(PropagateOrNot.DontPropagate); + var boneTransform = bone.AccessModelSpace(hkaPose.PropagateOrNot.DontPropagate); // Write our updated matrix to memory. var initialRot = boneTransform->Rotation.ToQuat(); @@ -78,7 +78,7 @@ public unsafe bool SetMatrix(bool start = true) { var bone = GetBone(); if (bone == null) return false; - var boneTransform = bone.AccessModelSpace(PropagateOrNot.DontPropagate); + var boneTransform = bone.AccessModelSpace(hkaPose.PropagateOrNot.DontPropagate); var matrix = Interop.Alloc.GetMatrix(boneTransform); if (start) diff --git a/Ktisis/Interface/Components/ActorsList.cs b/Ktisis/Interface/Components/ActorsList.cs index 4a0473ff0..0d5d3fcfe 100644 --- a/Ktisis/Interface/Components/ActorsList.cs +++ b/Ktisis/Interface/Components/ActorsList.cs @@ -6,7 +6,7 @@ using ImGuiNET; using FFXIVClientStructs.FFXIV.Client.Game.Object; using Dalamud.Interface; -using DalamudGameObject = Dalamud.Game.ClientState.Objects.Types.GameObject; +using DalamudGameObject = Dalamud.Game.ClientState.Objects.Types.IGameObject; using ObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind; using Ktisis.Structs.Actor; @@ -163,7 +163,7 @@ private unsafe static bool IsValidActor(long target) { private static bool IsValidActor(DalamudGameObject gameObject) => IsValidActor((long)gameObject.Address); private static bool IsNonNetworkObject(DalamudGameObject gameObject) => - gameObject.ObjectId == DalamudGameObject.InvalidGameObjectId; + gameObject.EntityId == 0xE0000000; private static string ExtraInfo(DalamudGameObject gameObject) { List info = new(); if (IsGposeActor(gameObject)) diff --git a/Ktisis/Interface/Components/AnimationControls.cs b/Ktisis/Interface/Components/AnimationControls.cs index 558d83643..d0c91ad25 100644 --- a/Ktisis/Interface/Components/AnimationControls.cs +++ b/Ktisis/Interface/Components/AnimationControls.cs @@ -1,7 +1,7 @@ using ImGuiNET; using Dalamud.Game.ClientState.Objects.Types; -using FFXIVClientStructs.Havok; +using FFXIVClientStructs.Havok.Animation.Playback.Control.Default; using Ktisis.Interop.Hooks; using Ktisis.Util; @@ -10,7 +10,7 @@ namespace Ktisis.Interface.Components { public static class AnimationControls { - public static unsafe void Draw(GameObject? target) { + public static unsafe void Draw(IGameObject? target) { // Animation control if (ImGui.CollapsingHeader("Animation Control")) { var control = PoseHooks.GetAnimationControl(target); diff --git a/Ktisis/Interface/Components/TransformTable.cs b/Ktisis/Interface/Components/TransformTable.cs index fa3a713f0..3ee62daeb 100644 --- a/Ktisis/Interface/Components/TransformTable.cs +++ b/Ktisis/Interface/Components/TransformTable.cs @@ -7,7 +7,8 @@ using Dalamud.Interface; -using FFXIVClientStructs.Havok; +using FFXIVClientStructs.Havok.Common.Base.Math.Quaternion; +using FFXIVClientStructs.Havok.Common.Base.Math.Vector; using Ktisis.Util; using Ktisis.Events; diff --git a/Ktisis/Interface/Windows/ActorEdit/EditCustomize.cs b/Ktisis/Interface/Windows/ActorEdit/EditCustomize.cs index c2b55a0ad..94e479c82 100644 --- a/Ktisis/Interface/Windows/ActorEdit/EditCustomize.cs +++ b/Ktisis/Interface/Windows/ActorEdit/EditCustomize.cs @@ -4,14 +4,13 @@ using System.Collections.Generic; using ImGuiNET; -using ImGuiScene; using Lumina.Excel; using Dalamud.Interface; using Dalamud.Interface.Components; using Dalamud.Game.ClientState.Objects.Enums; -using Dalamud.Interface.Internal; +using Dalamud.Interface.Textures.TextureWraps; using Ktisis.Util; using Ktisis.Data; @@ -124,7 +123,7 @@ private static void InvokeFeatureIcons(object[] args) { if (iconId == 0) iconId = (uint)CharaMakeType.FacialFeatures[8 * i]; - var icon = Services.Textures.GetIcon(iconId); + var icon = Services.Textures.GetFromGameIcon(iconId).GetWrapOrDefault(); if (icon != null) features.Add(icon); } FacialFeatureIcons = features; @@ -691,12 +690,12 @@ public static Dictionary> GetMenuOptions(uint index, var feat = feature.Value; if (feat == null || feat.FeatureId == 0) break; - var icon = Services.Textures.GetIcon(feat.Icon); + var icon = Services.Textures.GetFromGameIcon(feat.Icon).GetWrapOrEmpty(); if (icon != null) icons.Add(feat.FeatureId, icon); } } else { for (var x = 0; x < val.Count; x++) { - var icon = Services.Textures.GetIcon(val.Params[x]); + var icon = Services.Textures.GetFromGameIcon(val.Params[x]).GetWrapOrEmpty(); if (icon != null) icons.Add(val.Graphics[x], icon); } } diff --git a/Ktisis/Interface/Windows/ActorEdit/EditEquip.cs b/Ktisis/Interface/Windows/ActorEdit/EditEquip.cs index 594620bc8..2a038c657 100644 --- a/Ktisis/Interface/Windows/ActorEdit/EditEquip.cs +++ b/Ktisis/Interface/Windows/ActorEdit/EditEquip.cs @@ -6,12 +6,9 @@ using System.Threading.Tasks; using ImGuiNET; -using ImGuiScene; using Dalamud.Interface; -using Dalamud.Interface.Internal; -using Dalamud.Logging; -using Dalamud.Plugin.Services; +using Dalamud.Interface.Textures.TextureWraps; using Ktisis.Util; using Ktisis.Data; @@ -419,7 +416,7 @@ private static void DrawDyePickerHeader(dynamic i) public class ItemCache : IDisposable { private CancellationTokenSource? _tokenSrc; - private ushort? IconId; + private int? IconId; public object? Equip; public Item? Item; @@ -435,7 +432,7 @@ public void SetEquip(object? equip, EquipSlot slot) { _tokenSrc = new CancellationTokenSource(); Resolve(equip, slot, _tokenSrc.Token).ContinueWith(task => { if (task.Exception != null) - PluginLog.Error($"Error occurred while resolving item:\n{task.Exception}"); + Ktisis.Log.Error($"Error occurred while resolving item:\n{task.Exception}"); }, TaskContinuationOptions.OnlyOnFaulted); } @@ -448,7 +445,7 @@ private async Task Resolve(object? equip, EquipSlot slot, CancellationToken toke var newIconId = item?.Icon; if (newIconId != IconId) { - var newIcon = newIconId is ushort id ? Services.Textures.GetIcon(id) : null; + var newIcon = newIconId is int id ? Services.Textures.GetFromGameIcon(id).GetWrapOrEmpty() : null; if (token.IsCancellationRequested) { newIcon?.Dispose(); return; diff --git a/Ktisis/Interface/Windows/ConfigGui.cs b/Ktisis/Interface/Windows/ConfigGui.cs index 20bc7cf11..fb55b9171 100644 --- a/Ktisis/Interface/Windows/ConfigGui.cs +++ b/Ktisis/Interface/Windows/ConfigGui.cs @@ -48,7 +48,7 @@ public static void Hide() { public static void Draw() { if (!Visible) { if (!_isSaved) { - PluginLog.Verbose("Saving config..."); + Ktisis.Log.Verbose("Saving config..."); Services.PluginInterface.SavePluginConfig(Ktisis.Configuration); _isSaved = true; } @@ -679,7 +679,7 @@ public static void DrawReferencesTab(Configuration cfg) { public static bool TryChangeReference(Configuration cfg, int key, string newPath) { try { - var texture = Ktisis.UiBuilder.LoadImage(newPath); + var texture = Services.Textures.GetFromFile(newPath).GetWrapOrEmpty(); cfg.References[key] = new ReferenceInfo { Path = newPath, Showing = true, diff --git a/Ktisis/Interface/Windows/References.cs b/Ktisis/Interface/Windows/References.cs index f94a6006c..cecfe7104 100644 --- a/Ktisis/Interface/Windows/References.cs +++ b/Ktisis/Interface/Windows/References.cs @@ -3,10 +3,9 @@ using System.Linq; using System.Numerics; -using Dalamud.Interface.Internal; +using Dalamud.Interface.Textures.TextureWraps; using ImGuiNET; -using ImGuiScene; namespace Ktisis.Interface.Windows { internal static class References { @@ -55,7 +54,7 @@ public static bool LoadReference(KeyValuePair reference) { var path = reference.Value.Path; try { if (path == null) return false; - Textures[path] = Ktisis.UiBuilder.LoadImage(path); + Textures[path] = Services.Textures.GetFromFile(path).GetWrapOrEmpty(); return true; } catch (Exception e) { Logger.Error(e, "Failed to load reference image {0}", path ?? "null"); diff --git a/Ktisis/Interface/Windows/Workspace/Tabs/ActorTab.cs b/Ktisis/Interface/Windows/Workspace/Tabs/ActorTab.cs index b46ab4b5c..f10d5c32f 100644 --- a/Ktisis/Interface/Windows/Workspace/Tabs/ActorTab.cs +++ b/Ktisis/Interface/Windows/Workspace/Tabs/ActorTab.cs @@ -22,7 +22,7 @@ namespace Ktisis.Interface.Windows.Workspace.Tabs { public static class ActorTab { private static readonly NpcImport _npcImport = new(); - public unsafe static void Draw(GameObject target) { + public unsafe static void Draw(IGameObject target) { var actor = (Actor*)target.Address; if (actor == null) return; diff --git a/Ktisis/Interface/Windows/Workspace/Tabs/CameraTab.cs b/Ktisis/Interface/Windows/Workspace/Tabs/CameraTab.cs index 6cccc71d5..6649fad63 100644 --- a/Ktisis/Interface/Windows/Workspace/Tabs/CameraTab.cs +++ b/Ktisis/Interface/Windows/Workspace/Tabs/CameraTab.cs @@ -167,7 +167,7 @@ private unsafe static void DrawTargetLock() { var isFreecam = camera.WorkCamera != null; - var tarLock = camera.GetOrbitTarget() is GameObject actor ? (Actor*)actor.Address : null; + var tarLock = camera.GetOrbitTarget() is IGameObject actor ? (Actor*)actor.Address : null; var isTarLocked = tarLock != null || isFreecam; var target = tarLock != null ? tarLock : Ktisis.Target; diff --git a/Ktisis/Interface/Windows/Workspace/Tabs/PoseTab.cs b/Ktisis/Interface/Windows/Workspace/Tabs/PoseTab.cs index 1d30e3371..48184ee35 100644 --- a/Ktisis/Interface/Windows/Workspace/Tabs/PoseTab.cs +++ b/Ktisis/Interface/Windows/Workspace/Tabs/PoseTab.cs @@ -16,7 +16,7 @@ public static class PoseTab { public static PoseContainer _TempPose = new(); - public unsafe static void Draw(GameObject target) { + public unsafe static void Draw(IGameObject target) { var cfg = Ktisis.Configuration; var actor = (Actor*)target.Address; diff --git a/Ktisis/Interface/Windows/Workspace/Tabs/WorldTab.cs b/Ktisis/Interface/Windows/Workspace/Tabs/WorldTab.cs index d41328ac3..784ba6f47 100644 --- a/Ktisis/Interface/Windows/Workspace/Tabs/WorldTab.cs +++ b/Ktisis/Interface/Windows/Workspace/Tabs/WorldTab.cs @@ -44,7 +44,7 @@ private static void CheckData() { var weather = EnvService.GetEnvWeatherIds(); EnvService.GetWeatherIcons(weather, token).ContinueWith(result => { if (result.Exception != null) { - PluginLog.Error($"Failed to load weather data:\n{result.Exception}"); + Ktisis.Log.Error($"Failed to load weather data:\n{result.Exception}"); return; } else if (result.IsCanceled) return; diff --git a/Ktisis/Interface/Windows/Workspace/Workspace.cs b/Ktisis/Interface/Windows/Workspace/Workspace.cs index 09b381e60..dcecb7d0d 100644 --- a/Ktisis/Interface/Windows/Workspace/Workspace.cs +++ b/Ktisis/Interface/Windows/Workspace/Workspace.cs @@ -105,7 +105,7 @@ public static void Draw() { // Selection details - private unsafe static void SelectInfo(GameObject target) { + private unsafe static void SelectInfo(IGameObject target) { var actor = (Actor*)target.Address; var select = Skeleton.BoneSelect; diff --git a/Ktisis/Interop/Alloc.cs b/Ktisis/Interop/Alloc.cs index ab4a8e3ce..3efd6579c 100644 --- a/Ktisis/Interop/Alloc.cs +++ b/Ktisis/Interop/Alloc.cs @@ -2,10 +2,9 @@ using System.Numerics; using System.Runtime.InteropServices; -using Dalamud.Logging; - -using FFXIVClientStructs.Havok; using FFXIVClientStructs.FFXIV.Client.System.Memory; +using FFXIVClientStructs.Havok.Common.Base.Math.Matrix; +using FFXIVClientStructs.Havok.Common.Base.Math.QsTransform; namespace Ktisis.Interop { internal static class Alloc { @@ -46,7 +45,6 @@ internal unsafe GameAlloc(ulong align = 16) => Address = (nint)IMemorySpace.GetDefaultSpace()->Malloc(align); public unsafe void Dispose() { - PluginLog.Debug($"Disposing GameAlloc<{typeof(T)}>"); if (Disposed) return; IMemorySpace.Free(Data); // Free our allocated memory. Disposed = true; diff --git a/Ktisis/Interop/Hooks/CameraHooks.cs b/Ktisis/Interop/Hooks/CameraHooks.cs index ffb48995a..f6ebb9e24 100644 --- a/Ktisis/Interop/Hooks/CameraHooks.cs +++ b/Ktisis/Interop/Hooks/CameraHooks.cs @@ -58,7 +58,7 @@ private unsafe static nint ControlDetour(nint a1) { camera->LookAtVector += newPos - curPos; } } catch (Exception e) { - PluginLog.Error(e.ToString()); + Ktisis.Log.Error(e.ToString()); DisableHooks(); } @@ -85,7 +85,7 @@ private unsafe static nint ControlDetour(nint a1) { return tarMatrix; } } catch (Exception e) { - PluginLog.Error(e.ToString()); + Ktisis.Log.Error(e.ToString()); DisableHooks(); } diff --git a/Ktisis/Interop/Hooks/EventsHooks.cs b/Ktisis/Interop/Hooks/EventsHooks.cs index a02344e5d..b249f94c8 100644 --- a/Ktisis/Interop/Hooks/EventsHooks.cs +++ b/Ktisis/Interop/Hooks/EventsHooks.cs @@ -98,7 +98,7 @@ internal unsafe class MiragePrismMiragePlateAddon : IDisposable { public MiragePrismMiragePlateAddon() { var MiragePrismMiragePlateAgentInterface = Framework.Instance()->UIModule->GetAgentModule()->GetAgentByInternalId(AgentId.MiragePrismMiragePlate); - receiveEventHook ??= Services.Hooking.HookFromAddress(new IntPtr(MiragePrismMiragePlateAgentInterface->VTable->ReceiveEvent), OnReceiveEvent); + receiveEventHook ??= Services.Hooking.HookFromAddress(new IntPtr(MiragePrismMiragePlateAgentInterface->VirtualTable->ReceiveEvent), OnReceiveEvent); receiveEventHook?.Enable(); } diff --git a/Ktisis/Interop/Hooks/PoseHooks.cs b/Ktisis/Interop/Hooks/PoseHooks.cs index 62cf517ca..fc0875bc3 100644 --- a/Ktisis/Interop/Hooks/PoseHooks.cs +++ b/Ktisis/Interop/Hooks/PoseHooks.cs @@ -4,8 +4,9 @@ using Dalamud.Hooking; using Dalamud.Game.ClientState.Objects.Types; -using FFXIVClientStructs.Havok; using FFXIVClientStructs.FFXIV.Client.Graphics.Render; +using FFXIVClientStructs.Havok.Animation.Playback.Control.Default; +using FFXIVClientStructs.Havok.Animation.Rig; using Ktisis.Structs; using Ktisis.Structs.Actor; @@ -218,13 +219,13 @@ private static unsafe void SyncBone(hkaPose* bonesPose, int index) { CalculateBoneModelSpaceHook.Original(ref *bonesPose, index); } - public static unsafe bool IsGamePlaybackRunning(GameObject? gPoseTarget) { + public static unsafe bool IsGamePlaybackRunning(IGameObject? gPoseTarget) { var animationControl = GetAnimationControl(gPoseTarget); if (animationControl == null) return true; return animationControl->PlaybackSpeed == 1; } - public static unsafe hkaDefaultAnimationControl* GetAnimationControl(GameObject? go) { + public static unsafe hkaDefaultAnimationControl* GetAnimationControl(IGameObject? go) { if (go == null) return null; var actor = (Actor*)go.Address; diff --git a/Ktisis/Ktisis.cs b/Ktisis/Ktisis.cs index 48b9be5ce..0ce035e2c 100644 --- a/Ktisis/Ktisis.cs +++ b/Ktisis/Ktisis.cs @@ -4,6 +4,7 @@ using Dalamud.Game.Command; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Interface; +using Dalamud.Plugin.Services; using Ktisis.Camera; using Ktisis.Env; @@ -24,12 +25,13 @@ public sealed class Ktisis : IDalamudPlugin { public static string Version = $"Alpha {GetVersion()}"; public static Configuration Configuration { get; private set; } = null!; - public static UiBuilder UiBuilder { get; private set; } = null!; + public static IUiBuilder UiBuilder { get; private set; } = null!; + public static IPluginLog Log { get; private set; } = null!; public static bool IsInGPose => Services.ClientState.IsGPosing && IsGposeTargetPresent(); public unsafe static bool IsGposeTargetPresent() => (IntPtr)Services.Targets->GPoseTarget != IntPtr.Zero; - public unsafe static GameObject? GPoseTarget + public unsafe static IGameObject? GPoseTarget => IsInGPose ? Services.ObjectTable.CreateObjectReference((IntPtr)Services.Targets->GPoseTarget) : null; public unsafe static Actor* Target => GPoseTarget != null ? (Actor*)GPoseTarget.Address : null; @@ -37,10 +39,14 @@ public static string GetVersion() { return typeof(Ktisis).Assembly.GetName().Version!.ToString(fieldCount: 3); } - public Ktisis(DalamudPluginInterface pluginInterface) { + public Ktisis( + IDalamudPluginInterface pluginInterface, + IPluginLog log + ) { Services.Init(pluginInterface); Configuration = pluginInterface.GetPluginConfig() as Configuration ?? new Configuration(); UiBuilder = pluginInterface.UiBuilder; + Log = log; if (Configuration.IsFirstTimeInstall) { Configuration.IsFirstTimeInstall = false; diff --git a/Ktisis/Logger.cs b/Ktisis/Logger.cs index f3905c0a9..f1668b5f4 100644 --- a/Ktisis/Logger.cs +++ b/Ktisis/Logger.cs @@ -20,7 +20,7 @@ internal static void Fatal(string format, params object[] values) { if (IsExternal) WriteToConsole(ConsoleColor.DarkRed, format, values); else - PluginLog.Fatal(format, values); + Ktisis.Log.Fatal(format, values); } [StringFormatMethod("format")] @@ -28,14 +28,14 @@ internal static void Error(string format, params object[] values) { if (IsExternal) WriteToConsole(ConsoleColor.Red, format, values); else - PluginLog.Error(format, values); + Ktisis.Log.Error(format, values); } internal static void Error(Exception ex, string format, params object[] values) { if (IsExternal) WriteToConsole(ConsoleColor.Red, ex, format, values); else - PluginLog.Error(ex, format, values); + Ktisis.Log.Error(ex, format, values); } [StringFormatMethod("format")] @@ -43,7 +43,7 @@ internal static void Warning(string format, params object[] values) { if (IsExternal) WriteToConsole(ConsoleColor.Yellow, format, values); else - PluginLog.Warning(format, values); + Ktisis.Log.Warning(format, values); } [StringFormatMethod("format")] @@ -51,7 +51,7 @@ public static void Information(string format, params object[] values) { if (IsExternal) WriteToConsole(ConsoleColor.Cyan, format, values); else - PluginLog.Information(format, values); + Ktisis.Log.Information(format, values); } [StringFormatMethod("format")] @@ -59,7 +59,7 @@ internal static void Verbose(string format, params object[] values) { if (IsExternal) WriteToConsole(ConsoleColor.Gray, format, values); else - PluginLog.Verbose(format, values); + Ktisis.Log.Verbose(format, values); } [StringFormatMethod("format")] @@ -67,7 +67,7 @@ internal static void Debug(string format, params object[] values) { if (IsExternal) WriteToConsole(ConsoleColor.Magenta, format, values); else - PluginLog.Debug(format, values); + Ktisis.Log.Debug(format, values); } [StringFormatMethod("format")] diff --git a/Ktisis/Services.cs b/Ktisis/Services.cs index 6e0a54e78..711ad4b0a 100644 --- a/Ktisis/Services.cs +++ b/Ktisis/Services.cs @@ -7,7 +7,7 @@ namespace Ktisis { internal class Services { - [PluginService] internal static DalamudPluginInterface PluginInterface { get; private set; } = null!; + [PluginService] internal static IDalamudPluginInterface PluginInterface { get; private set; } = null!; [PluginService] internal static ICommandManager CommandManager { get; private set; } = null!; [PluginService] internal static ITextureProvider Textures { get; private set; } = null!; [PluginService] internal static IDataManager DataManager { get; private set; } = null!; @@ -23,7 +23,7 @@ internal class Services { internal unsafe static TargetSystem* Targets = TargetSystem.Instance(); internal unsafe static CameraManager* Camera = CameraManager.Instance(); - public static void Init(DalamudPluginInterface dalamud) { + public static void Init(IDalamudPluginInterface dalamud) { dalamud.Create(); } } diff --git a/Ktisis/Structs/Actor/Actor.cs b/Ktisis/Structs/Actor/Actor.cs index 24efdff37..41dac6086 100644 --- a/Ktisis/Structs/Actor/Actor.cs +++ b/Ktisis/Structs/Actor/Actor.cs @@ -91,7 +91,7 @@ public unsafe void Equip(int slot, WeaponEquip item) { if (Methods.ActorChangeWeapon == null) return; fixed (ActorDrawData* ptr = &DrawData) { - PluginLog.Information($"Setting to {item.Set} {item.Base} {item.Variant} {item.Dye}"); + Logger.Information($"Setting to {item.Set} {item.Base} {item.Variant} {item.Dye}"); Methods.ActorChangeWeapon(ptr, slot, default, 0, 1, 0, 0); Methods.ActorChangeWeapon(ptr, slot, item, 0, 1, 0, 0); @@ -155,11 +155,11 @@ public unsafe void ApplyCustomize(Customize custom) { // Actor redraw public void Redraw() { - var faceHack = GameObject.ObjectKind == (byte)ObjectKind.Pc; + var faceHack = GameObject.ObjectKind == ObjectKind.Pc; GameObject.DisableDraw(); - if (faceHack) GameObject.ObjectKind = (byte)ObjectKind.BattleNpc; + if (faceHack) GameObject.ObjectKind = ObjectKind.BattleNpc; GameObject.EnableDraw(); - if (faceHack) GameObject.ObjectKind = (byte)ObjectKind.Pc; + if (faceHack) GameObject.ObjectKind = ObjectKind.Pc; } // weapons diff --git a/Ktisis/Structs/Actor/ActorModel.cs b/Ktisis/Structs/Actor/ActorModel.cs index 0238aae76..77b9eb904 100644 --- a/Ktisis/Structs/Actor/ActorModel.cs +++ b/Ktisis/Structs/Actor/ActorModel.cs @@ -2,9 +2,10 @@ using System.Runtime.InteropServices; using System.Collections.Generic; -using FFXIVClientStructs.Havok; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using FFXIVClientStructs.FFXIV.Client.Graphics.Render; +using FFXIVClientStructs.Havok.Common.Base.Math.QsTransform; + using ModelType = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.CharacterBase.ModelType; namespace Ktisis.Structs.Actor { diff --git a/Ktisis/Structs/Actor/Equip/SetSources/GearSet.cs b/Ktisis/Structs/Actor/Equip/SetSources/GearSet.cs index 308c34595..e12f7de02 100644 --- a/Ktisis/Structs/Actor/Equip/SetSources/GearSet.cs +++ b/Ktisis/Structs/Actor/Equip/SetSources/GearSet.cs @@ -1,5 +1,4 @@ using System.Linq; -using System.Text; using System.Collections.Generic; using FFXIVClientStructs.FFXIV.Client.Game; @@ -18,9 +17,9 @@ public static unsafe Dictionary List() { for (var i = 0; i < _gearSetNumber; i++) { var gearset = raptureGearsetModule->GetGearset(i); - if (gearset->ID != i) break; + if (gearset->Id != i) break; if (!gearset->Flags.HasFlag(RaptureGearsetModule.GearsetFlag.Exists)) continue; - nameList.Add(i, Encoding.UTF8.GetString(gearset->Name, 0x2F)); + nameList.Add(i, gearset->NameString); } return nameList; @@ -58,18 +57,18 @@ public static unsafe Dictionary List() { // get item IDs from gearset List<(uint, EquipSlot)> itemsToRemodel = new() { - (gearset->MainHand.ItemID, EquipSlot.MainHand), - (gearset->OffHand.ItemID, EquipSlot.OffHand), - (gearset->Head.ItemID, EquipSlot.Head), - (gearset->Body.ItemID, EquipSlot.Chest), - (gearset->Hands.ItemID, EquipSlot.Hands), - (gearset->Legs.ItemID, EquipSlot.Legs), - (gearset->Feet.ItemID, EquipSlot.Feet), - (gearset->Ears.ItemID, EquipSlot.Earring), - (gearset->Neck.ItemID, EquipSlot.Necklace), - (gearset->Wrists.ItemID, EquipSlot.Bracelet), - (gearset->RingLeft.ItemID, EquipSlot.RingLeft), - (gearset->RingRight.ItemID, EquipSlot.RingRight), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.MainHand).ItemId, EquipSlot.MainHand), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.OffHand).ItemId, EquipSlot.OffHand), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.Head).ItemId, EquipSlot.Head), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.Body).ItemId, EquipSlot.Chest), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.Hands).ItemId, EquipSlot.Hands), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.Legs).ItemId, EquipSlot.Legs), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.Feet).ItemId, EquipSlot.Feet), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.Ears).ItemId, EquipSlot.Earring), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.Neck).ItemId, EquipSlot.Necklace), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.Wrists).ItemId, EquipSlot.Bracelet), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.RingLeft).ItemId, EquipSlot.RingLeft), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.RingRight).ItemId, EquipSlot.RingRight), }; @@ -84,12 +83,12 @@ public static unsafe Dictionary List() { InventoryItem? invItem = null; // get the inventory item by the gearset item id - var invItems = inventoryItems.Where(i => i.ItemID == id); - if (!invItems.Any()) invItems = inventoryItems.Where(i => i.ItemID == uint.Parse(id.ToString()[2..])); // not sure why, sometimes item IDs have numbers prepended to them (mostly "10") + var invItems = inventoryItems.Where(i => i.ItemId == id); + if (!invItems.Any()) invItems = inventoryItems.Where(i => i.ItemId == uint.Parse(id.ToString()[2..])); // not sure why, sometimes item IDs have numbers prepended to them (mostly "10") if (invItems.Any()) invItem = invItems.First(); // get the Item that contains the model Id - var items = Sets.ItemsSheet.Where(i => i.RowId == (invItem?.GlamourID == 0 ? invItem?.ItemID : invItem?.GlamourID)); + var items = Sets.ItemsSheet.Where(i => i.RowId == (invItem?.GlamourId == 0 ? invItem?.ItemId : invItem?.GlamourId)); if (items.Any()) item = items.First(); if (item == null) { @@ -98,7 +97,7 @@ public static unsafe Dictionary List() { continue; } - byte dye = (invItem?.Stain) ?? default; + byte dye = (invItem?.GetStain(0)) ?? default; itemsToEquip.Add((slot, Sets.ItemToEquipObject(item, dye, slot))); } diff --git a/Ktisis/Structs/Actor/Weapon.cs b/Ktisis/Structs/Actor/Weapon.cs index e638e7721..966e22efa 100644 --- a/Ktisis/Structs/Actor/Weapon.cs +++ b/Ktisis/Structs/Actor/Weapon.cs @@ -2,8 +2,8 @@ using System.Numerics; using System.Runtime.InteropServices; -using FFXIVClientStructs.Havok; using FFXIVClientStructs.FFXIV.Client.Graphics.Render; +using FFXIVClientStructs.Havok.Common.Base.Math.QsTransform; namespace Ktisis.Structs.Actor { [StructLayout(LayoutKind.Explicit)] diff --git a/Ktisis/Structs/Bones/Bone.cs b/Ktisis/Structs/Bones/Bone.cs index 1a101e30f..3f34a1bd9 100644 --- a/Ktisis/Structs/Bones/Bone.cs +++ b/Ktisis/Structs/Bones/Bone.cs @@ -1,9 +1,9 @@ using System.Numerics; using System.Collections.Generic; -using FFXIVClientStructs.Havok; using FFXIVClientStructs.FFXIV.Client.Graphics.Render; -using static FFXIVClientStructs.Havok.hkaPose; +using FFXIVClientStructs.Havok.Animation.Rig; +using FFXIVClientStructs.Havok.Common.Base.Math.QsTransform; using Ktisis.Localization; using Ktisis.Structs.Actor; @@ -46,7 +46,7 @@ public unsafe hkQsTransformf Transform { internal List? _setCategory = null; public List Categories => _setCategory ?? Category.GetForBone(HkaBone.Name.String); - public unsafe hkQsTransformf* AccessModelSpace(PropagateOrNot propagate = PropagateOrNot.DontPropagate) => Pose->AccessBoneModelSpace(Index, propagate); + public unsafe hkQsTransformf* AccessModelSpace(hkaPose.PropagateOrNot propagate = hkaPose.PropagateOrNot.DontPropagate) => Pose->AccessBoneModelSpace(Index, propagate); public unsafe hkQsTransformf* AccessLocalSpace() => Pose->AccessBoneLocalSpace(Index); public unsafe Vector3 GetWorldPos(ActorModel* model, ActorModel* parent = null) { @@ -142,7 +142,7 @@ public unsafe void PropagateChildren(hkQsTransformf* transform, Vector3 initialP var descendants = GetDescendants(includePartials, true); foreach (var child in descendants) { - var access = child.AccessModelSpace(PropagateOrNot.DontPropagate); + var access = child.AccessModelSpace(hkaPose.PropagateOrNot.DontPropagate); var offset = access->Translation.ToVector3() - sourcePos; offset = Vector3.Transform(offset, deltaRot); @@ -157,7 +157,7 @@ public unsafe void PropagateChildren(hkQsTransformf* transform, Vector3 initialP public unsafe void PropagateSibling(Quaternion deltaRot, SiblingLink mode = SiblingLink.Rotation) { if (mode == SiblingLink.None) return; - var access = AccessModelSpace(PropagateOrNot.DontPropagate); + var access = AccessModelSpace(hkaPose.PropagateOrNot.DontPropagate); var offset = access->Translation.ToVector3(); if (mode == SiblingLink.RotationMirrorX) diff --git a/Ktisis/Structs/Extensions/Havok.cs b/Ktisis/Structs/Extensions/Havok.cs index 50ae7d909..8fe9d9acb 100644 --- a/Ktisis/Structs/Extensions/Havok.cs +++ b/Ktisis/Structs/Extensions/Havok.cs @@ -1,7 +1,11 @@ using System.Numerics; -using FFXIVClientStructs.Havok; using FFXIVClientStructs.FFXIV.Client.Graphics.Render; +using FFXIVClientStructs.Havok.Animation.Rig; +using FFXIVClientStructs.Havok.Common.Base.Container.Array; +using FFXIVClientStructs.Havok.Common.Base.Math.QsTransform; +using FFXIVClientStructs.Havok.Common.Base.Math.Quaternion; +using FFXIVClientStructs.Havok.Common.Base.Math.Vector; using Ktisis.Structs.Bones; diff --git a/Ktisis/Structs/FFXIV/MiragePrismMiragePlate.cs b/Ktisis/Structs/FFXIV/MiragePrismMiragePlate.cs index 83ae85280..e19a908e2 100644 --- a/Ktisis/Structs/FFXIV/MiragePrismMiragePlate.cs +++ b/Ktisis/Structs/FFXIV/MiragePrismMiragePlate.cs @@ -4,7 +4,6 @@ using FFXIVClientStructs.Attributes; using FFXIVClientStructs.FFXIV.Client.System.Framework; using FFXIVClientStructs.FFXIV.Client.UI.Agent; -using FFXIVClientStructs.FFXIV.Component.GUI; using Ktisis.Structs.Actor.Equip.SetSources; @@ -20,7 +19,7 @@ public unsafe partial struct MiragePrismMiragePlate { //[FieldOffset(40 + 36)] public IntPtr* PlatesPointer; //[FieldOffset(40 + 36)] public fixed MiragePage Plates[20]; // This would be ideal, TODO: try to find a way to achieve this - internal static AgentInterface* MiragePlateAgent() => Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.MiragePrismMiragePlate); + internal static AgentInterface* MiragePlateAgent() => Framework.Instance()->GetUIModule()->GetAgentModule()->GetAgentByInternalId(AgentId.MiragePrismMiragePlate); // this getter exists because we cannot specify a sized array in the variable public MiragePage[] Pages { diff --git a/Ktisis/Structs/Poses/Transform.cs b/Ktisis/Structs/Poses/Transform.cs index 2088d4bb9..5d7e66d6e 100644 --- a/Ktisis/Structs/Poses/Transform.cs +++ b/Ktisis/Structs/Poses/Transform.cs @@ -1,6 +1,6 @@ using System.Numerics; -using FFXIVClientStructs.Havok; +using FFXIVClientStructs.Havok.Common.Base.Math.QsTransform; namespace Ktisis.Structs.Poses { public class Transform { diff --git a/Ktisis/Util/NpcImportService.cs b/Ktisis/Util/NpcImportService.cs index 033fbd3af..ff8cb28e2 100644 --- a/Ktisis/Util/NpcImportService.cs +++ b/Ktisis/Util/NpcImportService.cs @@ -71,7 +71,7 @@ public static async Task> GetNpcList() { )); timer.Stop(); - PluginLog.Information($"NPC list retrieved in {timer.Elapsed.TotalMilliseconds:0.00}ms"); + Logger.Information($"NPC list retrieved in {timer.Elapsed.TotalMilliseconds:0.00}ms"); return list; } From 47e41f405aa85a0026629848e644c75274acaec9 Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Thu, 4 Jul 2024 10:41:58 +0100 Subject: [PATCH 02/23] Update missing signatures --- Ktisis/Data/Files/FfxivCharaDat.cs | 5 ----- Ktisis/Interop/Hooks/ActorHooks.cs | 2 +- Ktisis/Interop/Hooks/CameraHooks.cs | 10 +++++----- Ktisis/Interop/Hooks/EnvHooks.cs | 6 +++--- Ktisis/Interop/Hooks/EventsHooks.cs | 5 +++-- Ktisis/Interop/Hooks/GuiHooks.cs | 2 +- Ktisis/Interop/Hooks/PoseHooks.cs | 8 ++++---- Ktisis/Interop/Methods.cs | 4 ++-- Ktisis/Interop/StaticOffsets.cs | 6 ------ 9 files changed, 19 insertions(+), 29 deletions(-) diff --git a/Ktisis/Data/Files/FfxivCharaDat.cs b/Ktisis/Data/Files/FfxivCharaDat.cs index 77c6aef8b..9fef7e1d4 100644 --- a/Ktisis/Data/Files/FfxivCharaDat.cs +++ b/Ktisis/Data/Files/FfxivCharaDat.cs @@ -43,10 +43,5 @@ public unsafe string Note() { fixed (byte* ptr = NoteChars) return Marshal.PtrToStringAnsi((IntPtr)ptr) ?? ""; } - - public unsafe static FfxivCharaDat GetFromSlot(int slot) { - var addr = Interop.StaticOffsets.CharaDatData + 8 + 0x140*slot; - return *(FfxivCharaDat*)addr; - } } } diff --git a/Ktisis/Interop/Hooks/ActorHooks.cs b/Ktisis/Interop/Hooks/ActorHooks.cs index 84beadead..e9682213c 100644 --- a/Ktisis/Interop/Hooks/ActorHooks.cs +++ b/Ktisis/Interop/Hooks/ActorHooks.cs @@ -22,7 +22,7 @@ internal unsafe static IntPtr ControlGaze(nint a1) { // Init & Dispose internal static void Init() { - var controlGaze = Services.SigScanner.ScanText("40 53 41 54 41 55 48 81 EC ?? ?? ?? ?? 48 8B D9"); + var controlGaze = Services.SigScanner.ScanText("40 57 41 54 41 56 48 81 EC ?? ?? ?? ?? 48 8B F9"); ControlGazeHook = Services.Hooking.HookFromAddress(controlGaze, ControlGaze); ControlGazeHook.Enable(); } diff --git a/Ktisis/Interop/Hooks/CameraHooks.cs b/Ktisis/Interop/Hooks/CameraHooks.cs index f6ebb9e24..ac0381f1c 100644 --- a/Ktisis/Interop/Hooks/CameraHooks.cs +++ b/Ktisis/Interop/Hooks/CameraHooks.cs @@ -187,7 +187,7 @@ private static void DisableHooks() { internal unsafe static void Init() { // Native methods - var ctorAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? EB 03 48 8B C7 45 33 C0 48 89 03"); + var ctorAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ?? 89 B3 ?? ?? ?? ??"); GameCamera_Ctor = Marshal.GetDelegateForFunctionPointer(ctorAddr); // Hooks @@ -198,19 +198,19 @@ internal unsafe static void Init() { var actCamAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? F7 80"); ActiveCamHook = Services.Hooking.HookFromAddress(actCamAddr, GetActiveCamDetour); - var camEventAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 0F B6 F0 EB 34"); + var camEventAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 0F B6 F8 EB 34"); CameraEventHook = Services.Hooking.HookFromAddress(camEventAddr, CameraEventDetour); var camUiAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 80 BB ?? ?? ?? ?? ?? 74 0D 8B 53 28"); CameraUiHook = Services.Hooking.HookFromAddress(camUiAddr, CameraUiDetour); - var camVf17 = ((nint*)Services.SigScanner.GetStaticAddressFromSig("88 83 ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ?? 48 89 03 C6 83", 6))[17]; + var camVf17 = ((nint*)Services.SigScanner.GetStaticAddressFromSig("48 8D 05 ?? ?? ?? ?? C7 83 ?? ?? ?? ?? ?? ?? ?? ?? 48 89 03 33 C0 89 83 ?? ?? ?? ??"))[17]; TargetHook = Services.Hooking.HookFromAddress(camVf17, TargetDetour); - var viewMxAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 33 C0 48 89 83 ?? ?? ?? ?? 48 8B 9C 24"); + var viewMxAddr = Services.SigScanner.ScanText("48 89 5C 24 ?? 57 48 81 EC ?? ?? ?? ?? F6 81 ?? ?? ?? ?? ?? 48 8B D9 48 89 B4 24 ?? ?? ?? ??"); CalcViewMatrixHook = Services.Hooking.HookFromAddress(viewMxAddr, CalcViewMatrixDetour); - var collideAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 4C 8D 45 C7 89 83"); + var collideAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 4C 8B AC 24 ?? ?? ?? ?? 32 DB"); CameraCollisionHook = Services.Hooking.HookFromAddress(collideAddr, CameraCollisionDetour); } diff --git a/Ktisis/Interop/Hooks/EnvHooks.cs b/Ktisis/Interop/Hooks/EnvHooks.cs index 919616ed1..fc993ea7f 100644 --- a/Ktisis/Interop/Hooks/EnvHooks.cs +++ b/Ktisis/Interop/Hooks/EnvHooks.cs @@ -64,13 +64,13 @@ private static void DisableHooks() { // Init & Dispose public unsafe static void Init() { - var addr1 = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 49 8B 0E 48 8D 93 ?? ?? ?? ??"); + var addr1 = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 41 0F 28 CA"); EnvUpdateHook = Services.Hooking.HookFromAddress(addr1, EnvUpdateDetour); - var addr2 = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 44 38 63 30 74 05 0F 28 DE"); + var addr2 = Services.SigScanner.ScanText("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 0F 29 74 24 ?? 48 8B D9"); SkyTexHook = Services.Hooking.HookFromAddress(addr2, SkyTexDetour); - var addr3 = Services.SigScanner.ScanText("48 8B C4 48 89 58 18 57 48 81 EC ?? ?? ?? ?? 0F 29 70 E8 48 8B D9"); + var addr3 = Services.SigScanner.ScanText("48 8B C4 48 89 58 18 57 48 81 EC ?? ?? ?? ?? 0F B6 B9 ?? ?? ?? ??"); WaterRendererUpdateHook = Services.Hooking.HookFromAddress(addr3, WaterRendererUpdateDetour); } diff --git a/Ktisis/Interop/Hooks/EventsHooks.cs b/Ktisis/Interop/Hooks/EventsHooks.cs index b249f94c8..41d29e7ad 100644 --- a/Ktisis/Interop/Hooks/EventsHooks.cs +++ b/Ktisis/Interop/Hooks/EventsHooks.cs @@ -125,8 +125,9 @@ internal unsafe class ClickTargetAddon : IDisposable { private readonly Hook? leftClickTargetHook; public ClickTargetAddon() { - rightClickTargetHook ??= Services.Hooking.HookFromAddress(Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 48 8B CE E8 ?? ?? ?? ?? 48 85 C0 74 1B"), RightClickTargetDetour); - leftClickTargetHook ??= Services.Hooking.HookFromAddress(Services.SigScanner.ScanText("E8 ?? ?? ?? ?? BA ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 84 C0 74 16"), LeftClickTargetDetour); + // TODO + //rightClickTargetHook ??= Services.Hooking.HookFromAddress(Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 48 8B CE E8 ?? ?? ?? ?? 48 85 C0 74 1B"), RightClickTargetDetour); + //leftClickTargetHook ??= Services.Hooking.HookFromAddress(Services.SigScanner.ScanText("E8 ?? ?? ?? ?? BA ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 84 C0 74 16"), LeftClickTargetDetour); } public void Enable() { diff --git a/Ktisis/Interop/Hooks/GuiHooks.cs b/Ktisis/Interop/Hooks/GuiHooks.cs index b24aaa27b..3a5b74d3d 100644 --- a/Ktisis/Interop/Hooks/GuiHooks.cs +++ b/Ktisis/Interop/Hooks/GuiHooks.cs @@ -40,7 +40,7 @@ internal unsafe static void UpdateTarName(IntPtr a1) { // Init & dispose internal static void Init() { - var tarName = Services.SigScanner.ScanText("40 56 48 83 EC 50 48 8B 05 ?? ?? ?? ?? 48 8B F1 48 85 C0"); + var tarName = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 48 8D 8E ?? ?? ?? ?? 0F 28 74 24 ??"); TarNameHook = Services.Hooking.HookFromAddress(tarName, UpdateTarName); TarNameHook.Enable(); } diff --git a/Ktisis/Interop/Hooks/PoseHooks.cs b/Ktisis/Interop/Hooks/PoseHooks.cs index fc0875bc3..506341567 100644 --- a/Ktisis/Interop/Hooks/PoseHooks.cs +++ b/Ktisis/Interop/Hooks/PoseHooks.cs @@ -56,20 +56,20 @@ internal static unsafe void Init() { var syncModelSpace = Services.SigScanner.ScanText("48 83 EC 18 80 79 38 00"); SyncModelSpaceHook = Services.Hooking.HookFromAddress(syncModelSpace, SyncModelSpaceDetour); - var lookAtIK = Services.SigScanner.ScanText("48 8B C4 48 89 58 08 48 89 70 10 F3 0F 11 58 ??"); + var lookAtIK = Services.SigScanner.ScanText("48 8B C4 48 89 58 08 48 89 70 10 F3 0F 11 58"); LookAtIKHook = Services.Hooking.HookFromAddress(lookAtIK, LookAtIKDetour); - var animFrozen = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 0F B6 F0 84 C0 74 0E"); + var animFrozen = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 0F B6 F8 84 C0 74 12"); AnimFrozenHook = Services.Hooking.HookFromAddress(animFrozen, AnimFrozenDetour); - var updatePos = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? EB 29 48 8B 5F 08"); + var updatePos = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 84 DB 74 45"); UpdatePosHook = Services.Hooking.HookFromAddress(updatePos, UpdatePosDetour); var loadSkele = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 48 C1 E5 08"); SetSkeletonHook = Services.Hooking.HookFromAddress(loadSkele, SetSkeletonDetour); SetSkeletonHook.Enable(); - var loadBust = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? F6 84 24 ?? ?? ?? ?? ?? 0F 28 74 24 ??"); + var loadBust = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 0F 28 7C 24 ?? 0F 28 74 24 ?? 4C 8B 74 24 ??"); BustHook = Services.Hooking.HookFromAddress(loadBust, BustDetour); } diff --git a/Ktisis/Interop/Methods.cs b/Ktisis/Interop/Methods.cs index cbc7aa97c..ff7b386e5 100644 --- a/Ktisis/Interop/Methods.cs +++ b/Ktisis/Interop/Methods.cs @@ -34,8 +34,8 @@ private static TDelegate Retrieve(string sig) internal static void Init() { ActorLookAt = Retrieve("40 53 55 57 41 56 41 57 48 83 EC 70"); - ActorChangeEquip = Retrieve("E8 ?? ?? ?? ?? 41 B5 01 FF C6"); - ActorChangeWeapon = Retrieve("E8 ?? ?? ?? ?? 80 7F 25 00"); + ActorChangeEquip = Retrieve("E8 ?? ?? ?? ?? B1 01 41 FF C6"); + ActorChangeWeapon = Retrieve("E8 ?? ?? ?? ?? 4C 8B 45 7F"); GetMatrix = Retrieve("E8 ?? ?? ?? ?? 48 8D 4C 24 ?? 48 89 4c 24 ?? 4C 8D 4D ?? 4C 8D 44 24 ??"); } } diff --git a/Ktisis/Interop/StaticOffsets.cs b/Ktisis/Interop/StaticOffsets.cs index af1f53a94..6f3e1e9ba 100644 --- a/Ktisis/Interop/StaticOffsets.cs +++ b/Ktisis/Interop/StaticOffsets.cs @@ -1,8 +1,5 @@ namespace Ktisis.Interop { internal static class StaticOffsets { - // Address of loaded FFXIV_CHARA files in memory. - internal static nint CharaDatData; - // If this is NOP'd, Anam posing is enabled. internal unsafe static byte* FreezePosition; internal unsafe static byte* FreezeRotation; @@ -16,9 +13,6 @@ internal static class StaticOffsets { // Init internal unsafe static void Init() { - var datAddr = *(nint*)Services.SigScanner.GetStaticAddressFromSig("48 8B 05 ?? ?? ?? ?? 48 C7 44 24 24 05 00 00 00 C6 84 24"); - CharaDatData = *(nint*)(datAddr + 1392); - FreezePosition = (byte*)Services.SigScanner.ScanText("41 0F 29 24 12"); FreezeRotation = (byte*)Services.SigScanner.ScanText("41 0F 29 5C 12 10"); FreezeScale = (byte*)Services.SigScanner.ScanText("41 0F 29 44 12 20"); From 1a98eb40dfb4724067be6ddf3f8743463ed6947e Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Thu, 4 Jul 2024 11:30:09 +0100 Subject: [PATCH 03/23] more dalamud api changes --- .../Windows/ActorEdit/EditCustomize.cs | 34 ++++++++----------- .../Interface/Windows/ActorEdit/EditEquip.cs | 14 +++----- Ktisis/Interface/Windows/ConfigGui.cs | 2 +- Ktisis/Interface/Windows/References.cs | 10 +++--- Ktisis/Ktisis.cs | 4 --- 5 files changed, 27 insertions(+), 37 deletions(-) diff --git a/Ktisis/Interface/Windows/ActorEdit/EditCustomize.cs b/Ktisis/Interface/Windows/ActorEdit/EditCustomize.cs index 94e479c82..5d6f01042 100644 --- a/Ktisis/Interface/Windows/ActorEdit/EditCustomize.cs +++ b/Ktisis/Interface/Windows/ActorEdit/EditCustomize.cs @@ -10,7 +10,7 @@ using Dalamud.Interface; using Dalamud.Interface.Components; using Dalamud.Game.ClientState.Objects.Enums; -using Dalamud.Interface.Textures.TextureWraps; +using Dalamud.Interface.Textures; using Ktisis.Util; using Ktisis.Data; @@ -27,7 +27,7 @@ public struct MenuOption { public CustomizeIndex ColorIndex = 0; public uint[] Colors = Array.Empty(); - public Dictionary? Select = null; + public Dictionary? Select = null; public MenuOption(Menu option) => Option = option; } @@ -70,7 +70,7 @@ public static class EditCustomize { public static int FaceType = -1; public static string FacialFeatureName = ""; - public static List? FacialFeatureIcons = null; + public static List? FacialFeatureIcons = null; public static CharaMakeType? CharaMakeType; @@ -102,15 +102,11 @@ private static void InvokeMakeData(object[] args) { CustomIndex = index; FacialFeatureIcons = null; } - - private readonly static AsyncTask GetFeatureIcons = new(InvokeFeatureIcons); - private static void InvokeFeatureIcons(object[] args) { - if (args[0] is not Customize custom) - return; - + + private static void GetFeatureIcons(Customize custom) { if (CharaMakeType == null) return; - var features = new List(); + var features = new List(); for (var i = 0; i < 7; i++) { var index = custom.FaceType - 1 + (8 * i); if (custom.Race == Race.Hrothgar) @@ -123,7 +119,7 @@ private static void InvokeFeatureIcons(object[] args) { if (iconId == 0) iconId = (uint)CharaMakeType.FacialFeatures[8 * i]; - var icon = Services.Textures.GetFromGameIcon(iconId).GetWrapOrDefault(); + var icon = Services.Textures.GetFromGameIcon(iconId); if (icon != null) features.Add(icon); } FacialFeatureIcons = features; @@ -338,7 +334,7 @@ public static void DrawIconSelector(Customize custom, MenuOption option, int _va bool click; if (sel!.ContainsKey(val)) - click = ImGui.ImageButton(sel[val].ImGuiHandle, IconSize); + click = ImGui.ImageButton(sel[val].GetWrapOrEmpty().ImGuiHandle, IconSize); else click = ImGui.Button($"{val}", ButtonIconSize); @@ -501,8 +497,8 @@ public static bool DrawColorList(uint[] colors, ref byte value) { // Facial feature selector public static void DrawFacialFeatures(Customize custom) { - if ((FacialFeatureIcons == null || custom.FaceType != FaceType) && !GetFeatureIcons.IsRunning) - GetFeatureIcons.Run(custom); + if ((FacialFeatureIcons == null || custom.FaceType != FaceType)) + GetFeatureIcons(custom); if (FacialFeatureIcons == null) return; @@ -523,7 +519,7 @@ public static void DrawFacialFeatures(Customize custom) { if (i == 7) // Legacy tattoo button |= ImGui.Button("Legacy\nTattoo", ButtonIconSize); else - button |= ImGui.ImageButton(FacialFeatureIcons[i].ImGuiHandle, IconSize); + button |= ImGui.ImageButton(FacialFeatureIcons[i].GetWrapOrEmpty().ImGuiHandle, IconSize); ImGui.PopStyleColor(); if (button) { @@ -578,7 +574,7 @@ public unsafe static void DrawIconList(Customize custom, MenuOption option) { foreach (var (val, icon) in option.Select!) { if (icon == null) continue; - if (ImGui.ImageButton(icon.ImGuiHandle, ListIconSize)) { + if (ImGui.ImageButton(icon.GetWrapOrEmpty().ImGuiHandle, ListIconSize)) { custom.Bytes[(uint)opt.Index] = (byte)val; Apply(custom); } @@ -674,7 +670,7 @@ public static Dictionary> GetMenuOptions(uint index, var opt = new MenuOption(val); if (val.HasIcon) { - var icons = new Dictionary(); + var icons = new Dictionary(); if (val.IsFeature) { var featMake = CharaMakeType?.FeatureMake.Value; if (featMake == null) continue; @@ -690,12 +686,12 @@ public static Dictionary> GetMenuOptions(uint index, var feat = feature.Value; if (feat == null || feat.FeatureId == 0) break; - var icon = Services.Textures.GetFromGameIcon(feat.Icon).GetWrapOrEmpty(); + var icon = Services.Textures.GetFromGameIcon(feat.Icon); if (icon != null) icons.Add(feat.FeatureId, icon); } } else { for (var x = 0; x < val.Count; x++) { - var icon = Services.Textures.GetFromGameIcon(val.Params[x]).GetWrapOrEmpty(); + var icon = Services.Textures.GetFromGameIcon(val.Params[x]); if (icon != null) icons.Add(val.Graphics[x], icon); } } diff --git a/Ktisis/Interface/Windows/ActorEdit/EditEquip.cs b/Ktisis/Interface/Windows/ActorEdit/EditEquip.cs index 2a038c657..12268a301 100644 --- a/Ktisis/Interface/Windows/ActorEdit/EditEquip.cs +++ b/Ktisis/Interface/Windows/ActorEdit/EditEquip.cs @@ -8,7 +8,7 @@ using ImGuiNET; using Dalamud.Interface; -using Dalamud.Interface.Textures.TextureWraps; +using Dalamud.Interface.Textures; using Ktisis.Util; using Ktisis.Data; @@ -110,7 +110,7 @@ public unsafe static void DrawSelector(EquipSlot slot) { Equipped[slot].SetEquip(equipObj, slot); var item = Equipped[slot]; - var icon = item.Icon?.ImGuiHandle ?? 0; + var icon = item.Icon?.GetWrapOrEmpty().ImGuiHandle ?? 0; ImGui.PushID((int)slot); if (ImGui.ImageButton(icon, IconSize) && SlotSelect == null) OpenSelector(slot); @@ -420,7 +420,7 @@ public class ItemCache : IDisposable { public object? Equip; public Item? Item; - public IDalamudTextureWrap? Icon; + public ISharedImmediateTexture? Icon; public ItemCache(object? equip, EquipSlot slot) => SetEquip(equip, slot); @@ -445,19 +445,15 @@ private async Task Resolve(object? equip, EquipSlot slot, CancellationToken toke var newIconId = item?.Icon; if (newIconId != IconId) { - var newIcon = newIconId is int id ? Services.Textures.GetFromGameIcon(id).GetWrapOrEmpty() : null; - if (token.IsCancellationRequested) { - newIcon?.Dispose(); + var newIcon = newIconId is int id ? Services.Textures.GetFromGameIcon(id) : null; + if (token.IsCancellationRequested) return; - } IconId = newIconId; - Icon?.Dispose(); Icon = newIcon; } } public void Dispose() { - Icon?.Dispose(); Icon = null; } diff --git a/Ktisis/Interface/Windows/ConfigGui.cs b/Ktisis/Interface/Windows/ConfigGui.cs index fb55b9171..b4cfd9f24 100644 --- a/Ktisis/Interface/Windows/ConfigGui.cs +++ b/Ktisis/Interface/Windows/ConfigGui.cs @@ -679,7 +679,7 @@ public static void DrawReferencesTab(Configuration cfg) { public static bool TryChangeReference(Configuration cfg, int key, string newPath) { try { - var texture = Services.Textures.GetFromFile(newPath).GetWrapOrEmpty(); + var texture = Services.Textures.GetFromFile(newPath); cfg.References[key] = new ReferenceInfo { Path = newPath, Showing = true, diff --git a/Ktisis/Interface/Windows/References.cs b/Ktisis/Interface/Windows/References.cs index cecfe7104..b67f8f981 100644 --- a/Ktisis/Interface/Windows/References.cs +++ b/Ktisis/Interface/Windows/References.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Numerics; +using Dalamud.Interface.Textures; using Dalamud.Interface.Textures.TextureWraps; using ImGuiNET; @@ -10,7 +11,7 @@ namespace Ktisis.Interface.Windows { internal static class References { /** Maps file paths to loaded textures. */ - public static Dictionary Textures = new(); + public static Dictionary Textures = new(); // Draw @@ -24,9 +25,11 @@ public static void Draw() { public static void DrawReferenceWindow(Configuration cfg, int key, ReferenceInfo reference) { if (!reference.Showing) return; if (reference.Path is not string path) return; - if (!Textures.TryGetValue(path, out var texture)) + if (!Textures.TryGetValue(path, out var sharedTex)) return; + var texture = sharedTex.GetWrapOrEmpty(); + var size = new Vector2(texture.Width, texture.Height); ImGui.SetNextWindowSize(size, ImGuiCond.FirstUseEver); ImGui.SetNextWindowSizeConstraints(new Vector2(50, 50), size); @@ -54,7 +57,7 @@ public static bool LoadReference(KeyValuePair reference) { var path = reference.Value.Path; try { if (path == null) return false; - Textures[path] = Services.Textures.GetFromFile(path).GetWrapOrEmpty(); + Textures[path] = Services.Textures.GetFromFile(path); return true; } catch (Exception e) { Logger.Error(e, "Failed to load reference image {0}", path ?? "null"); @@ -67,7 +70,6 @@ public static void DisposeUnreferencedTextures(Configuration cfg) { var paths = cfg.References.Values.Select(x => x.Path ?? ""); var unloadPaths = loadedPaths.Except(paths); foreach (var path in unloadPaths) { - Textures[path].Dispose(); Textures.Remove(path); } } diff --git a/Ktisis/Ktisis.cs b/Ktisis/Ktisis.cs index 0ce035e2c..83fa8a216 100644 --- a/Ktisis/Ktisis.cs +++ b/Ktisis/Ktisis.cs @@ -125,10 +125,6 @@ public void Dispose() { Input.Dispose(); HistoryManager.Dispose(); - - foreach (var (_, texture) in References.Textures) { - texture.Dispose(); - } } private void OnCommand(string command, string arguments) { From 2f1a96752f16e7c8e6189776e37183d58758ef35 Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Thu, 4 Jul 2024 13:05:40 +0100 Subject: [PATCH 04/23] more signature updates --- Ktisis/Interop/Hooks/EventsHooks.cs | 6 ++++-- Ktisis/Interop/Hooks/PoseHooks.cs | 2 +- Ktisis/Interop/Methods.cs | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Ktisis/Interop/Hooks/EventsHooks.cs b/Ktisis/Interop/Hooks/EventsHooks.cs index 41d29e7ad..1cef958f0 100644 --- a/Ktisis/Interop/Hooks/EventsHooks.cs +++ b/Ktisis/Interop/Hooks/EventsHooks.cs @@ -131,11 +131,13 @@ public ClickTargetAddon() { } public void Enable() { - rightClickTargetHook?.Enable(); - leftClickTargetHook?.Enable(); + //rightClickTargetHook?.Enable(); + //leftClickTargetHook?.Enable(); } public void Dispose() { + return; + // Verify presence of hooks, in case of calls when it's already been disposed if (!(bool)rightClickTargetHook?.IsDisposed!) { if ((bool)rightClickTargetHook?.IsEnabled!) diff --git a/Ktisis/Interop/Hooks/PoseHooks.cs b/Ktisis/Interop/Hooks/PoseHooks.cs index 506341567..3da9443d0 100644 --- a/Ktisis/Interop/Hooks/PoseHooks.cs +++ b/Ktisis/Interop/Hooks/PoseHooks.cs @@ -159,7 +159,7 @@ private static unsafe char SetSkeletonDetour(Skeleton* a1, ushort a2, nint a3) { if (actor->Model == null || actor->Model->Skeleton != a1) continue; PoseContainer container = new(); - container.Store(actor->Model->Skeleton); + container.Store((FFXIVClientStructs.FFXIV.Client.Graphics.Render.Skeleton*)actor->Model->Skeleton); PreservedPoses[actor->ObjectID] = container; } } diff --git a/Ktisis/Interop/Methods.cs b/Ktisis/Interop/Methods.cs index ff7b386e5..9cbf355fb 100644 --- a/Ktisis/Interop/Methods.cs +++ b/Ktisis/Interop/Methods.cs @@ -33,7 +33,7 @@ private static TDelegate Retrieve(string sig) => Marshal.GetDelegateForFunctionPointer(Services.SigScanner.ScanText(sig)); internal static void Init() { - ActorLookAt = Retrieve("40 53 55 57 41 56 41 57 48 83 EC 70"); + ActorLookAt = Retrieve("E8 ?? ?? ?? ?? 8B D3 8B CB"); ActorChangeEquip = Retrieve("E8 ?? ?? ?? ?? B1 01 41 FF C6"); ActorChangeWeapon = Retrieve("E8 ?? ?? ?? ?? 4C 8B 45 7F"); GetMatrix = Retrieve("E8 ?? ?? ?? ?? 48 8D 4C 24 ?? 48 89 4c 24 ?? 4C 8D 4D ?? 4C 8D 44 24 ??"); From 7d0240072987504b0fb13ca8bfd3db8c0d767326 Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Thu, 4 Jul 2024 13:12:57 +0100 Subject: [PATCH 05/23] fix camera matrices --- Ktisis/Structs/Extensions/Camera.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Ktisis/Structs/Extensions/Camera.cs b/Ktisis/Structs/Extensions/Camera.cs index e746724ab..e2fa6d462 100644 --- a/Ktisis/Structs/Extensions/Camera.cs +++ b/Ktisis/Structs/Extensions/Camera.cs @@ -6,12 +6,15 @@ namespace Ktisis.Structs.Extensions { public static class Camera { public unsafe static Matrix4x4 GetProjectionMatrix(this GameCamera camera) { - var ptr = (byte*)&camera; - return *(Matrix4x4*)((IntPtr)camera.CameraBase.SceneCamera.RenderCamera + 80); + var cam = camera.CameraBase.SceneCamera.RenderCamera; + var proj = cam->ProjectionMatrix; + var clip = cam->FarPlane / (cam->FarPlane - cam->NearPlane); + proj.M43 = -(clip * cam->NearPlane); + proj.M33 = -clip; + return proj; } public unsafe static Matrix4x4 GetViewMatrix(this GameCamera camera) { - var ptr = (byte*)&camera; - var view = *(Matrix4x4*)(ptr + 0xB0); + var view = camera.CameraBase.SceneCamera.ViewMatrix; view.M44 = 1; return view; } From b0babc8aae5750fd344564defec5bac6d13ecffe Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Thu, 4 Jul 2024 14:26:21 +0100 Subject: [PATCH 06/23] update offsets --- Ktisis/Data/Files/AnamCharaFile.cs | 2 +- Ktisis/Helpers/PoseHelpers.cs | 1 - Ktisis/Overlay/Skeleton.cs | 2 ++ Ktisis/Structs/Actor/Actor.cs | 9 +++------ Ktisis/Structs/Actor/ActorDrawData.cs | 2 +- Ktisis/Structs/Actor/ActorModel.cs | 16 ++++++++-------- Ktisis/Structs/Actor/Equipment.cs | 12 +++++++----- Ktisis/Structs/Actor/Weapon.cs | 9 ++++++--- 8 files changed, 28 insertions(+), 25 deletions(-) diff --git a/Ktisis/Data/Files/AnamCharaFile.cs b/Ktisis/Data/Files/AnamCharaFile.cs index 4949bbb4e..231d464f0 100644 --- a/Ktisis/Data/Files/AnamCharaFile.cs +++ b/Ktisis/Data/Files/AnamCharaFile.cs @@ -378,7 +378,7 @@ public unsafe void Write(Actor* actor, bool isMainHand) { if (wep.Set != 0) { wep.Base = ModelBase; wep.Variant = ModelVariant; - wep.Dye = DyeId; + wep.Dye = (byte)DyeId; } actor->Equip(isMainHand ? 0 : 1, wep); diff --git a/Ktisis/Helpers/PoseHelpers.cs b/Ktisis/Helpers/PoseHelpers.cs index 6633f9aa6..74e3e62e3 100644 --- a/Ktisis/Helpers/PoseHelpers.cs +++ b/Ktisis/Helpers/PoseHelpers.cs @@ -3,7 +3,6 @@ using Ktisis.Data.Files; using Ktisis.Data.Serialization; -using Ktisis.Data.Serialization.Converters; using Ktisis.Structs.Actor; using Ktisis.Structs.Poses; using Ktisis.Interop.Hooks; diff --git a/Ktisis/Overlay/Skeleton.cs b/Ktisis/Overlay/Skeleton.cs index b8cb38627..070dc8cf9 100644 --- a/Ktisis/Overlay/Skeleton.cs +++ b/Ktisis/Overlay/Skeleton.cs @@ -97,6 +97,8 @@ public unsafe static void DrawModelSkeleton(ActorModel* model, ActorModel* paren var camera = Services.Camera->GetActiveCamera(); var skeleton = pose->Skeleton; + if (skeleton == null) continue; + for (var i = 1; i < skeleton->Bones.Length; i++) { var bone = model->Skeleton->GetBone(p, i, parentModel != null); if (_setCategory != null) bone._setCategory = _setCategory; diff --git a/Ktisis/Structs/Actor/Actor.cs b/Ktisis/Structs/Actor/Actor.cs index 41dac6086..27db0016c 100644 --- a/Ktisis/Structs/Actor/Actor.cs +++ b/Ktisis/Structs/Actor/Actor.cs @@ -2,15 +2,12 @@ using System.Collections.Generic; using System.Runtime.InteropServices; -using Dalamud.Logging; - using FFXIVClientStructs.FFXIV.Client.Game.Object; using FFXIVClientStructs.FFXIV.Client.Graphics.Render; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using Ktisis.Interop; using Ktisis.Data.Excel; -using Ktisis.Structs.Actor.State; namespace Ktisis.Structs.Actor { [StructLayout(LayoutKind.Explicit, Size = 0x84A)] @@ -23,14 +20,14 @@ public struct Actor { [FieldOffset(0x114)] public RenderMode RenderMode; [FieldOffset(0x1AC)] public uint ModelId; - [FieldOffset(0x6F8)] public ActorDrawData DrawData; + [FieldOffset(0x708)] public ActorDrawData DrawData; [FieldOffset(0x89E)] public bool IsHatHidden; - public const int GazeOffset = 0xCB0; + public const int GazeOffset = 0xD00; [FieldOffset(GazeOffset + 0x10)] public ActorGaze Gaze; - [FieldOffset(0x1B2C)] public float Transparency; + [FieldOffset(0x21C8)] public float Transparency; public unsafe string? GetName() { fixed (byte* ptr = GameObject.Name) diff --git a/Ktisis/Structs/Actor/ActorDrawData.cs b/Ktisis/Structs/Actor/ActorDrawData.cs index 4c8d14fae..5038999fc 100644 --- a/Ktisis/Structs/Actor/ActorDrawData.cs +++ b/Ktisis/Structs/Actor/ActorDrawData.cs @@ -5,7 +5,7 @@ namespace Ktisis.Structs.Actor { public struct ActorDrawData { [FieldOffset(0x010)] public Weapon MainHand; [FieldOffset(0x080)] public Weapon OffHand; - [FieldOffset(0x0E8)] public Weapon Prop; + [FieldOffset(0x0F0)] public Weapon Prop; [FieldOffset(0x160)] public Equipment Equipment; [FieldOffset(0x188)] public Customize Customize; diff --git a/Ktisis/Structs/Actor/ActorModel.cs b/Ktisis/Structs/Actor/ActorModel.cs index 77b9eb904..b1ce3f2a6 100644 --- a/Ktisis/Structs/Actor/ActorModel.cs +++ b/Ktisis/Structs/Actor/ActorModel.cs @@ -2,8 +2,8 @@ using System.Runtime.InteropServices; using System.Collections.Generic; -using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using FFXIVClientStructs.FFXIV.Client.Graphics.Render; +using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using FFXIVClientStructs.Havok.Common.Base.Math.QsTransform; using ModelType = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.CharacterBase.ModelType; @@ -26,18 +26,18 @@ public struct ActorModel { [FieldOffset(0x148)] public unsafe Breasts* Bust; - [FieldOffset(0x274)] public float Height; + [FieldOffset(0x2A4)] public float Height; [FieldOffset(0x370)] public nint Sklb; - [FieldOffset(0x8F0)] public Customize Customize; + [FieldOffset(0x9D0)] public Customize Customize; - [FieldOffset(0x8F4)] public unsafe fixed uint DemiEquip[5]; - [FieldOffset(0x910)] public unsafe fixed uint HumanEquip[10]; + [FieldOffset(0x918)] public unsafe fixed ulong DemiEquip[5]; + [FieldOffset(0x9F0)] public unsafe fixed ulong HumanEquip[10]; - [FieldOffset(0x2B0)] public float WeatherWetness; // Set to 1.0f when raining and not covered or umbrella'd - [FieldOffset(0x2B4)] public float SwimmingWetness; // Set to 1.0f when in water - [FieldOffset(0x2B8)] public float WetnessDepth; // Set to ~character height in GPose and higher values when swimming or diving. + [FieldOffset(0x2E0)] public float WeatherWetness; // Set to 1.0f when raining and not covered or umbrella'd + [FieldOffset(0x2E4)] public float SwimmingWetness; // Set to 1.0f when in water + [FieldOffset(0x2E8)] public float WetnessDepth; // Set to ~character height in GPose and higher values when swimming or diving. private unsafe CharacterBase* AsCharacter() { fixed (ActorModel* self = &this) diff --git a/Ktisis/Structs/Actor/Equipment.cs b/Ktisis/Structs/Actor/Equipment.cs index a73d8214a..8b01801bd 100644 --- a/Ktisis/Structs/Actor/Equipment.cs +++ b/Ktisis/Structs/Actor/Equipment.cs @@ -19,20 +19,22 @@ public struct Equipment { [FieldOffset(0x24)] public ItemEquip RingLeft; } - [StructLayout(LayoutKind.Explicit, Size = 0x4)] + [StructLayout(LayoutKind.Explicit, Size = 0x8)] public struct ItemEquip { [FieldOffset(0)] public ushort Id; [FieldOffset(2)] public byte Variant; [FieldOffset(3)] public byte Dye; + [FieldOffset(4)] public byte Dye2; - public static explicit operator ItemEquip(uint num) => new() { + public static explicit operator ItemEquip(ulong num) => new() { Id = (ushort)(num & 0xFFFF), Variant = (byte)(num >> 16 & 0xFF), - Dye = (byte)(num >> 24) + Dye = (byte)(num >> 24), + Dye2 = (byte)(num >> 32) }; - public static explicit operator uint(ItemEquip equip) - => (uint)(equip.Id | (equip.Variant << 16) | (equip.Dye << 24)); + public static explicit operator ulong(ItemEquip equip) + => (uint)(equip.Id | (equip.Variant << 16) | (equip.Dye << 24)) | ((ulong)equip.Dye2 << 32); public bool Equals(ItemEquip other) => Id == other.Id && Variant == other.Variant; } diff --git a/Ktisis/Structs/Actor/Weapon.cs b/Ktisis/Structs/Actor/Weapon.cs index 966e22efa..3010fca75 100644 --- a/Ktisis/Structs/Actor/Weapon.cs +++ b/Ktisis/Structs/Actor/Weapon.cs @@ -9,7 +9,7 @@ namespace Ktisis.Structs.Actor { [StructLayout(LayoutKind.Explicit)] public struct Weapon { [FieldOffset(0x00)] public WeaponEquip Equip; - [FieldOffset(0x08)] public unsafe WeaponModel* Model; + [FieldOffset(0x18)] public unsafe WeaponModel* Model; [FieldOffset(0x40)] public bool IsSheathed; [FieldOffset(0x60)] public WeaponFlags Flags; @@ -27,7 +27,10 @@ public struct WeaponEquip { [FieldOffset(0x00)] public ushort Set; [FieldOffset(0x02)] public ushort Base; [FieldOffset(0x04)] public ushort Variant; - [FieldOffset(0x06)] public ushort Dye; + [FieldOffset(0x06)] public byte Dye; + [FieldOffset(0x07)] public byte Dye2; + + [FieldOffset(0x00)] public ulong Value; } [StructLayout(LayoutKind.Explicit)] @@ -41,7 +44,7 @@ public struct WeaponModel { [FieldOffset(0xA0)] public unsafe Skeleton* Skeleton; - [FieldOffset(0x8F0)] public WeaponEquip Equip; + [FieldOffset(0x9D0)] public WeaponEquip Equip; } public enum WeaponSlot { From 46f1bb75025127c09ad65089408b1f7e2136dd91 Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Sat, 6 Jul 2024 18:24:08 +0100 Subject: [PATCH 07/23] 2nd dye channel support --- Ktisis/Data/Files/AnamCharaFile.cs | 12 ++++-- .../Interface/Windows/ActorEdit/EditEquip.cs | 41 +++++++++++++------ Ktisis/Structs/Actor/Equipment.cs | 22 +++++++++- Ktisis/Structs/Actor/Types/IEquipItem.cs | 7 ++++ Ktisis/Structs/Actor/Weapon.cs | 22 +++++++++- 5 files changed, 86 insertions(+), 18 deletions(-) create mode 100644 Ktisis/Structs/Actor/Types/IEquipItem.cs diff --git a/Ktisis/Data/Files/AnamCharaFile.cs b/Ktisis/Data/Files/AnamCharaFile.cs index 231d464f0..a95e757f8 100644 --- a/Ktisis/Data/Files/AnamCharaFile.cs +++ b/Ktisis/Data/Files/AnamCharaFile.cs @@ -361,6 +361,7 @@ public WeaponSave(WeaponEquip from) { ModelBase = from.Base; ModelVariant = from.Variant; DyeId = from.Dye; + DyeId2 = from.Dye2; } public Vector3 Color { get; set; } @@ -368,7 +369,8 @@ public WeaponSave(WeaponEquip from) { public ushort ModelSet { get; set; } public ushort ModelBase { get; set; } public ushort ModelVariant { get; set; } - public ushort DyeId { get; set; } + public byte DyeId { get; set; } + public byte DyeId2 { get; set; } public unsafe void Write(Actor* actor, bool isMainHand) { var wep = new WeaponEquip() { @@ -378,7 +380,8 @@ public unsafe void Write(Actor* actor, bool isMainHand) { if (wep.Set != 0) { wep.Base = ModelBase; wep.Variant = ModelVariant; - wep.Dye = (byte)DyeId; + wep.Dye = DyeId; + wep.Dye2 = DyeId2; } actor->Equip(isMainHand ? 0 : 1, wep); @@ -394,17 +397,20 @@ public ItemSave(ItemEquip from) { ModelBase = from.Id; ModelVariant = from.Variant; DyeId = from.Dye; + DyeId2 = from.Dye2; } public ushort ModelBase { get; set; } public byte ModelVariant { get; set; } public byte DyeId { get; set; } + public byte DyeId2 { get; set; } public unsafe void Write(Actor* actor, EquipIndex index) { var item = new ItemEquip() { Id = ModelBase, Variant = ModelVariant, - Dye = DyeId + Dye = DyeId, + Dye2 = DyeId2 }; actor->Equip(index, item); } diff --git a/Ktisis/Interface/Windows/ActorEdit/EditEquip.cs b/Ktisis/Interface/Windows/ActorEdit/EditEquip.cs index 12268a301..37b5237fa 100644 --- a/Ktisis/Interface/Windows/ActorEdit/EditEquip.cs +++ b/Ktisis/Interface/Windows/ActorEdit/EditEquip.cs @@ -17,6 +17,7 @@ using Ktisis.Structs.Actor; using Ktisis.Structs.Actor.Equip; using Ktisis.Interface.Components; +using Ktisis.Structs.Actor.Types; namespace Ktisis.Interface.Windows.ActorEdit { public static class EditEquip { @@ -41,6 +42,7 @@ public static class EditEquip { private static bool DrawSetDyeSelection = false; private static EquipSlot? SlotSelectDye; + private static int SelectDyeIndex; public static IEnumerable? Dyes => DyeData.Get(); @@ -152,9 +154,9 @@ public unsafe static void DrawSelector(EquipSlot slot) { ImGui.PopItemWidth(); ImGui.SameLine(); - var dye = Dyes!.FirstOrDefault(i => i.RowId == (isWeapon ? ((WeaponEquip)equipObj).Dye : ((ItemEquip)equipObj).Dye)); - if (ImGui.ColorButton($"{dye?.Name} [{dye?.RowId}]##{slot}", dye?.ColorVector4 ?? default, ImGuiColorEditFlags.NoBorder)) - OpenDyePicker(slot); + DrawDyeButton((IEquipItem)equipObj, slot, 0); + ImGui.SameLine(); + DrawDyeButton((IEquipItem)equipObj, slot, 1); if (equipObj is WeaponEquip) { ImGui.SameLine(); @@ -179,7 +181,7 @@ public unsafe static void DrawSelector(EquipSlot slot) { if (SlotSelect == slot) DrawSelectorList(slot, equipObj); if (SlotSelectDye == slot) - DrawDyePicker(slot, equipObj); + DrawDyePicker(slot, equipObj, SelectDyeIndex); } public static void OpenSelector(EquipSlot slot) { @@ -191,7 +193,26 @@ public static void CloseSelector() { SlotItems = null; } - public static void OpenDyePicker(EquipSlot slot) => SlotSelectDye = slot; + private static void DrawDyeButton(IEquipItem item, EquipSlot slot, int index) { + var dye = Dyes!.FirstOrDefault(i => i.RowId == item.GetDye(index)); + if (ImGui.ColorButton($"{dye?.Name} [{dye?.RowId}]##{slot}_{index}", dye?.ColorVector4 ?? default, ImGuiColorEditFlags.NoBorder)) + OpenDyePicker(slot, index); + if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) + SetDye(item, slot, index, 0); + } + + private unsafe static void SetDye(IEquipItem item, EquipSlot slot, int index, byte value) { + item.SetDye(index, value); + if (item is WeaponEquip wepEquip) + Target->Equip((int)slot, wepEquip); + else if (item is ItemEquip itemEquip) + Target->Equip(SlotToIndex(slot), itemEquip); + } + + public static void OpenDyePicker(EquipSlot slot, int index) { + SlotSelectDye = slot; + SelectDyeIndex = index; + } public static void CloseDyePicker() => SlotSelectDye = null; public static void OpenSetSelector() => DrawSetSelection = true; @@ -307,7 +328,7 @@ public unsafe static void DrawSetSelectorList() private static int DyeLastSubOrder = -1; private const int DyePickerWidth = 485; - public static unsafe void DrawDyePicker(EquipSlot slot, object equipObj) + public static unsafe void DrawDyePicker(EquipSlot slot, object equipObj, int index) { PopupSelect.HoverPopupWindow( PopupSelect.HoverPopupWindowFlags.SearchBar @@ -318,13 +339,7 @@ public static unsafe void DrawDyePicker(EquipSlot slot, object equipObj) DrawDyePickerHeader, DrawDyePickerItem, (i) => { // on Select - if (equipObj is WeaponEquip wep) { - wep.Dye = (byte)i.RowId; - Target->Equip((int)slot, wep); - } else if (equipObj is ItemEquip item) { - item.Dye = (byte)i.RowId; - Target->Equip(SlotToIndex(slot), item); - } + SetDye((IEquipItem)equipObj, slot, index, (byte)i.RowId); }, CloseDyePicker, // on close ref DyeSearch, diff --git a/Ktisis/Structs/Actor/Equipment.cs b/Ktisis/Structs/Actor/Equipment.cs index 8b01801bd..46a0dd41d 100644 --- a/Ktisis/Structs/Actor/Equipment.cs +++ b/Ktisis/Structs/Actor/Equipment.cs @@ -1,5 +1,7 @@ using System.Runtime.InteropServices; +using Ktisis.Structs.Actor.Types; + namespace Ktisis.Structs.Actor { [StructLayout(LayoutKind.Explicit)] public struct Equipment { @@ -20,7 +22,7 @@ public struct Equipment { } [StructLayout(LayoutKind.Explicit, Size = 0x8)] - public struct ItemEquip { + public struct ItemEquip : IEquipItem { [FieldOffset(0)] public ushort Id; [FieldOffset(2)] public byte Variant; [FieldOffset(3)] public byte Dye; @@ -37,6 +39,24 @@ public static explicit operator ulong(ItemEquip equip) => (uint)(equip.Id | (equip.Variant << 16) | (equip.Dye << 24)) | ((ulong)equip.Dye2 << 32); public bool Equals(ItemEquip other) => Id == other.Id && Variant == other.Variant; + + public byte GetDye(int index) { + return index switch { + 1 => this.Dye2, + _ => this.Dye + }; + } + + public void SetDye(int index, byte value) { + switch (index) { + case 0: + this.Dye = value; + break; + case 1: + this.Dye2 = value; + break; + } + } } public enum EquipIndex : uint { diff --git a/Ktisis/Structs/Actor/Types/IEquipItem.cs b/Ktisis/Structs/Actor/Types/IEquipItem.cs new file mode 100644 index 000000000..7ca611705 --- /dev/null +++ b/Ktisis/Structs/Actor/Types/IEquipItem.cs @@ -0,0 +1,7 @@ +namespace Ktisis.Structs.Actor.Types { + public interface IEquipItem { + public byte GetDye(int index); + + public void SetDye(int index, byte value); + } +} \ No newline at end of file diff --git a/Ktisis/Structs/Actor/Weapon.cs b/Ktisis/Structs/Actor/Weapon.cs index 3010fca75..cb5f14e97 100644 --- a/Ktisis/Structs/Actor/Weapon.cs +++ b/Ktisis/Structs/Actor/Weapon.cs @@ -5,6 +5,8 @@ using FFXIVClientStructs.FFXIV.Client.Graphics.Render; using FFXIVClientStructs.Havok.Common.Base.Math.QsTransform; +using Ktisis.Structs.Actor.Types; + namespace Ktisis.Structs.Actor { [StructLayout(LayoutKind.Explicit)] public struct Weapon { @@ -23,7 +25,7 @@ public unsafe void SetEquip(WeaponEquip item) { } [StructLayout(LayoutKind.Explicit)] - public struct WeaponEquip { + public struct WeaponEquip : IEquipItem { [FieldOffset(0x00)] public ushort Set; [FieldOffset(0x02)] public ushort Base; [FieldOffset(0x04)] public ushort Variant; @@ -31,6 +33,24 @@ public struct WeaponEquip { [FieldOffset(0x07)] public byte Dye2; [FieldOffset(0x00)] public ulong Value; + + public byte GetDye(int index) { + return index switch { + 1 => this.Dye2, + _ => this.Dye + }; + } + + public void SetDye(int index, byte value) { + switch (index) { + case 0: + this.Dye = value; + break; + case 1: + this.Dye2 = value; + break; + } + } } [StructLayout(LayoutKind.Explicit)] From 1147a3f319f48853195f336ff64d17a3c71796ba Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Sat, 6 Jul 2024 19:54:35 +0100 Subject: [PATCH 08/23] implement facewear/glasses --- Ktisis/Data/Excel/Glasses.cs | 18 +++++++ Ktisis/Data/Files/AnamCharaFile.cs | 4 ++ .../Interface/Windows/ActorEdit/EditEquip.cs | 51 ++++++++++++++++++- Ktisis/Interop/Methods.cs | 4 ++ Ktisis/Structs/Actor/Actor.cs | 7 +++ Ktisis/Structs/Actor/ActorDrawData.cs | 2 + Ktisis/Structs/Actor/ActorModel.cs | 2 +- 7 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 Ktisis/Data/Excel/Glasses.cs diff --git a/Ktisis/Data/Excel/Glasses.cs b/Ktisis/Data/Excel/Glasses.cs new file mode 100644 index 000000000..2837d37cf --- /dev/null +++ b/Ktisis/Data/Excel/Glasses.cs @@ -0,0 +1,18 @@ +using Dalamud.Utility; + +using Lumina.Data; +using Lumina.Excel; + +namespace Ktisis.Data.Excel { + [Sheet("Glasses")] + public class Glasses : ExcelRow { + public string Name { get; set; } = string.Empty; + + public override void PopulateData(RowParser parser, Lumina.GameData gameData, Language language) { + base.PopulateData(parser, gameData, language); + + var name = parser.ReadColumn(13); + this.Name = !name.IsNullOrEmpty() ? name : "None"; + } + } +} \ No newline at end of file diff --git a/Ktisis/Data/Files/AnamCharaFile.cs b/Ktisis/Data/Files/AnamCharaFile.cs index a95e757f8..96759369e 100644 --- a/Ktisis/Data/Files/AnamCharaFile.cs +++ b/Ktisis/Data/Files/AnamCharaFile.cs @@ -86,6 +86,8 @@ public enum SaveModes { public ItemSave? Wrists { get; set; } public ItemSave? LeftRing { get; set; } public ItemSave? RightRing { get; set; } + + public ushort? Glasses { get; set; } // extended appearance // NOTE: extended weapon values are stored in the WeaponSave @@ -128,6 +130,7 @@ public void WriteToFile(Actor actor, SaveModes mode) { Hands = GetItemSave(actor, EquipIndex.Hands); Legs = GetItemSave(actor, EquipIndex.Legs); Feet = GetItemSave(actor, EquipIndex.Feet); + Glasses = actor.DrawData.Glasses; } if (IncludeSection(SaveModes.EquipmentAccessories, mode)) { @@ -215,6 +218,7 @@ public unsafe void Apply(Actor* actor, SaveModes mode) { Hands?.Write(actor, EquipIndex.Hands); Legs?.Write(actor, EquipIndex.Legs); Feet?.Write(actor, EquipIndex.Feet); + if (Glasses != null) actor->SetGlasses(Glasses.Value); } if (IncludeSection(SaveModes.EquipmentAccessories, mode)) { diff --git a/Ktisis/Interface/Windows/ActorEdit/EditEquip.cs b/Ktisis/Interface/Windows/ActorEdit/EditEquip.cs index 37b5237fa..f452d68cd 100644 --- a/Ktisis/Interface/Windows/ActorEdit/EditEquip.cs +++ b/Ktisis/Interface/Windows/ActorEdit/EditEquip.cs @@ -19,6 +19,8 @@ using Ktisis.Interface.Components; using Ktisis.Structs.Actor.Types; +using Lumina.Excel; + namespace Ktisis.Interface.Windows.ActorEdit { public static class EditEquip { // Constants @@ -31,15 +33,19 @@ public static class EditEquip { public static IEnumerable? Items => ItemData.Get(); + public static ExcelSheet? Glasses; + public static Dictionary Equipped = new(); public static EquipSlot? SlotSelect; public static IEnumerable? SlotItems; + private static string GlassesSearch = ""; private static string ItemSearch = ""; private static string SetSearch = ""; private static string DyeSearch = ""; private static bool DrawSetSelection = false; private static bool DrawSetDyeSelection = false; + private static bool DrawGlassesSelection = false; private static EquipSlot? SlotSelectDye; private static int SelectDyeIndex; @@ -69,6 +75,11 @@ public static void Draw() { if (Items == null || Dyes == null) return; DrawControls(); + + ImGui.Spacing(); + DrawFaceWear(); + ImGui.Spacing(); + ImGui.Spacing(); ImGui.BeginGroup(); for (var i = 2; i < 13; i++) { @@ -84,10 +95,26 @@ public static void Draw() { DrawSelector(slot); } ImGui.EndGroup(); - + ImGui.EndTabItem(); } + public unsafe static void DrawFaceWear() { + Glasses ??= Services.DataManager.GetExcelSheet()!; + + var glassesId = EditActor.Target->DrawData.Glasses; + var glasses = Glasses.GetRow(glassesId); + var name = glasses?.Name ?? "None"; + if (ImGui.BeginCombo("Glasses", name)) { + DrawGlassesSelection = true; + ImGui.CloseCurrentPopup(); + ImGui.EndCombo(); + } + + if (DrawGlassesSelection) + DrawGlassesSelector(); + } + public unsafe static void DrawSelector(EquipSlot slot) { var tar = EditActor.Target; var isWeapon = slot == EquipSlot.MainHand || slot == EquipSlot.OffHand; @@ -295,6 +322,28 @@ public unsafe static void DrawSelectorList(EquipSlot slot, object equipObj) ); } + private unsafe static void DrawGlassesSelector() { + if (Glasses == null) return; + + PopupSelect.HoverPopupWindow( + PopupSelect.HoverPopupWindowFlags.SelectorList | PopupSelect.HoverPopupWindowFlags.SearchBar, + Glasses, + (e, input) => e.Where(i => i.Name.Contains(input, StringComparison.OrdinalIgnoreCase)), + (i, a) => ( // draw Line + ImGui.Selectable(i.Name, a), + ImGui.IsItemFocused() + ), + (i) => { // on Select + Target->SetGlasses((ushort)i.RowId); + }, + () => DrawGlassesSelection = false, + ref GlassesSearch, + "Glasses Select", + "##glasses_list", + "##glasses_search" + ); + } + public unsafe static void DrawSetSelectorList() { IEnumerable sets = Sets.FindSets(); diff --git a/Ktisis/Interop/Methods.cs b/Ktisis/Interop/Methods.cs index 9cbf355fb..be7b11c0a 100644 --- a/Ktisis/Interop/Methods.cs +++ b/Ktisis/Interop/Methods.cs @@ -21,6 +21,9 @@ internal class Methods { internal unsafe delegate void ChangeWeaponDelegate(ActorDrawData* writeTo, int slot, WeaponEquip weapon, byte a4, byte a5, byte a6, byte a7); // a4-a7 is always 0,1,0,0. internal static ChangeWeaponDelegate? ActorChangeWeapon; + internal unsafe delegate void ChangeGlassesDelegate(ActorDrawData* writeTo, int slot, ushort id); + internal static ChangeGlassesDelegate? ChangeGlasses; + // Get world matrix [UnmanagedFunctionPointer(CallingConvention.Cdecl)] @@ -36,6 +39,7 @@ internal static void Init() { ActorLookAt = Retrieve("E8 ?? ?? ?? ?? 8B D3 8B CB"); ActorChangeEquip = Retrieve("E8 ?? ?? ?? ?? B1 01 41 FF C6"); ActorChangeWeapon = Retrieve("E8 ?? ?? ?? ?? 4C 8B 45 7F"); + ChangeGlasses = Retrieve("E8 ?? ?? ?? ?? EB 50 44 8B 03"); GetMatrix = Retrieve("E8 ?? ?? ?? ?? 48 8D 4C 24 ?? 48 89 4c 24 ?? 4C 8D 4D ?? 4C 8D 44 24 ??"); } } diff --git a/Ktisis/Structs/Actor/Actor.cs b/Ktisis/Structs/Actor/Actor.cs index 27db0016c..14ee43dd8 100644 --- a/Ktisis/Structs/Actor/Actor.cs +++ b/Ktisis/Structs/Actor/Actor.cs @@ -99,6 +99,13 @@ public unsafe void Equip(int slot, WeaponEquip item) { } } + public unsafe void SetGlasses(ushort id) { + if (Methods.ChangeGlasses == null) return; + + fixed (ActorDrawData* ptr = &DrawData) + Methods.ChangeGlasses(ptr, 0, id); + } + // Change customize - no redraw method public unsafe bool UpdateCustomize() { diff --git a/Ktisis/Structs/Actor/ActorDrawData.cs b/Ktisis/Structs/Actor/ActorDrawData.cs index 5038999fc..096fb8038 100644 --- a/Ktisis/Structs/Actor/ActorDrawData.cs +++ b/Ktisis/Structs/Actor/ActorDrawData.cs @@ -9,5 +9,7 @@ public struct ActorDrawData { [FieldOffset(0x160)] public Equipment Equipment; [FieldOffset(0x188)] public Customize Customize; + + [FieldOffset(0x1D0)] public ushort Glasses; } } diff --git a/Ktisis/Structs/Actor/ActorModel.cs b/Ktisis/Structs/Actor/ActorModel.cs index b1ce3f2a6..45b9250d5 100644 --- a/Ktisis/Structs/Actor/ActorModel.cs +++ b/Ktisis/Structs/Actor/ActorModel.cs @@ -33,7 +33,7 @@ public struct ActorModel { [FieldOffset(0x9D0)] public Customize Customize; [FieldOffset(0x918)] public unsafe fixed ulong DemiEquip[5]; - [FieldOffset(0x9F0)] public unsafe fixed ulong HumanEquip[10]; + [FieldOffset(0x9F0)] public unsafe fixed ulong HumanEquip[11]; [FieldOffset(0x2E0)] public float WeatherWetness; // Set to 1.0f when raining and not covered or umbrella'd [FieldOffset(0x2E4)] public float SwimmingWetness; // Set to 1.0f when in water From d297efa4a487ae22e80580c7d9ee952af6567e35 Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Sat, 6 Jul 2024 21:38:26 +0100 Subject: [PATCH 09/23] Weather fixes --- Ktisis/Env/EnvService.cs | 13 +++++++------ Ktisis/Env/WeatherInfo.cs | 15 +++------------ .../Interface/Windows/Workspace/Tabs/WorldTab.cs | 10 +++++----- Ktisis/Interop/Hooks/EnvHooks.cs | 15 +++++++++------ 4 files changed, 24 insertions(+), 29 deletions(-) diff --git a/Ktisis/Env/EnvService.cs b/Ktisis/Env/EnvService.cs index a26b9a782..af248a112 100644 --- a/Ktisis/Env/EnvService.cs +++ b/Ktisis/Env/EnvService.cs @@ -3,7 +3,7 @@ using System.Threading; using System.Threading.Tasks; -using Dalamud.Interface.Textures.TextureWraps; +using Dalamud.Interface.Textures; using FFXIVClientStructs.FFXIV.Client.Graphics.Environment; @@ -47,7 +47,7 @@ private static void OnGPoseChange(bool state) { private static uint CurSky = uint.MaxValue; public static readonly object SkyLock = new(); - public static IDalamudTextureWrap? SkyTex; + public static ISharedImmediateTexture? SkyTex; public static void GetSkyImage(uint sky) { if (sky == CurSky) return; @@ -60,16 +60,15 @@ public static void GetSkyImage(uint sky) { } lock (SkyLock) { - SkyTex?.Dispose(); SkyTex = result.Result; } }); } - private static async Task GetSkyboxTex(uint skyId) { + private static async Task GetSkyboxTex(uint skyId) { await Task.Yield(); Ktisis.Log.Verbose($"Retrieving skybox texture: {skyId:000}"); - return Services.Textures.GetFromGame($"bgcommon/nature/sky/texture/sky_{skyId:000}.tex").GetWrapOrEmpty(); + return Services.Textures.GetFromGame($"bgcommon/nature/sky/texture/sky_{skyId:000}.tex"); } public unsafe static byte[] GetEnvWeatherIds() { @@ -91,11 +90,13 @@ public static async Task> GetWeatherIcons(IEnumerable new("None"); - - private class NullTexture : IDalamudTextureWrap { - public nint ImGuiHandle { get; } = nint.Zero; - public int Width { get; } = 0; - public int Height { get; } = 0; - - public void Dispose() { } - } } } diff --git a/Ktisis/Interface/Windows/Workspace/Tabs/WorldTab.cs b/Ktisis/Interface/Windows/Workspace/Tabs/WorldTab.cs index 784ba6f47..d34f455e0 100644 --- a/Ktisis/Interface/Windows/Workspace/Tabs/WorldTab.cs +++ b/Ktisis/Interface/Windows/Workspace/Tabs/WorldTab.cs @@ -138,7 +138,7 @@ private static bool DrawWeatherSelect(int current, out int clickedId) { ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, style.FramePadding with { Y = padding }); if (ImGui.BeginCombo(WeatherLabel, currentInfo != null ? "##" : "Unknown")) { foreach (var weatherInfo in Weather) { - if (ImGui.Selectable($"##EnvWeather{weatherInfo.RowId}", weatherInfo.RowId == current)) { + if (ImGui.Selectable($"##EnvWeather{weatherInfo.RowId}", weatherInfo.RowId == current, ImGuiSelectableFlags.DontClosePopups)) { click = true; clickedId = (int)weatherInfo.RowId; } @@ -160,7 +160,7 @@ private static void DrawWeatherLabel(WeatherInfo weather, bool adjustPad = false var style = ImGui.GetStyle(); var height = ImGui.GetFrameHeight(); - if (weather.Icon != null) { + //if (weather.Icon != null) { ImGui.SameLine(0, 0); ImGui.SetCursorPosX(ImGui.GetCursorStartPos().X + style.ItemInnerSpacing.X); @@ -168,9 +168,9 @@ private static void DrawWeatherLabel(WeatherInfo weather, bool adjustPad = false if (adjustPad) posY -= style.FramePadding.Y; ImGui.SetCursorPosY(posY); - ImGui.Image(weather.Icon.ImGuiHandle, WeatherIconSize); + ImGui.Image(weather.Icon?.GetWrapOrEmpty().ImGuiHandle ?? 0, WeatherIconSize); ImGui.SameLine(); - } + //} ImGui.Text(weather.Name); } @@ -187,7 +187,7 @@ private static bool DrawSkySelect(ref uint skyId) { lock (EnvService.SkyLock) { if (EnvService.SkyTex != null) - ImGui.Image(EnvService.SkyTex.ImGuiHandle, buttonSize); + ImGui.Image(EnvService.SkyTex.GetWrapOrEmpty().ImGuiHandle, buttonSize); } ImGui.SameLine(); diff --git a/Ktisis/Interop/Hooks/EnvHooks.cs b/Ktisis/Interop/Hooks/EnvHooks.cs index fc993ea7f..edd4a0d18 100644 --- a/Ktisis/Interop/Hooks/EnvHooks.cs +++ b/Ktisis/Interop/Hooks/EnvHooks.cs @@ -8,23 +8,26 @@ public static class EnvHooks { // Hooks private unsafe delegate nint EnvUpdateDelegate(EnvManagerEx* env, nint a2); - private delegate bool SkyTexDelegate(nint a1, uint a2, float a3, float a4); + private delegate nint SkyTexDelegate(nint a1, nint a2); private static Hook EnvUpdateHook = null!; private unsafe static nint EnvUpdateDetour(EnvManagerEx* env, nint a2) { if (Ktisis.IsInGPose && EnvService.TimeOverride != null) env->Time = EnvService.TimeOverride.Value; + return EnvUpdateHook.Original(env, a2); } private static Hook SkyTexHook = null!; - private static bool SkyTexDetour(nint a1, uint a2, float a3, float a4) { + private unsafe static nint SkyTexDetour(nint a1, nint a2) { + var res = SkyTexHook.Original(a1, a2); + if (Ktisis.IsInGPose && EnvService.SkyOverride != null) - a2 = EnvService.SkyOverride.Value; - return SkyTexHook.Original(a1, a2, a3, a4); + *(uint*)(a1 + 8) = EnvService.SkyOverride.Value; + + return res; } - private delegate nint WaterRendererUpdateDelegate(nint a1); private static Hook WaterRendererUpdateHook = null!; private static nint WaterRendererUpdateDetour(nint a1) { @@ -67,7 +70,7 @@ public unsafe static void Init() { var addr1 = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 41 0F 28 CA"); EnvUpdateHook = Services.Hooking.HookFromAddress(addr1, EnvUpdateDetour); - var addr2 = Services.SigScanner.ScanText("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 0F 29 74 24 ?? 48 8B D9"); + var addr2 = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 49 3B F5 75 0D"); SkyTexHook = Services.Hooking.HookFromAddress(addr2, SkyTexDetour); var addr3 = Services.SigScanner.ScanText("48 8B C4 48 89 58 18 57 48 81 EC ?? ?? ?? ?? 0F B6 B9 ?? ?? ?? ??"); From 094e287e58133fa568d1a8fd71e4e22f1a13b6aa Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Sat, 6 Jul 2024 21:40:32 +0100 Subject: [PATCH 10/23] cleanup --- .../Windows/Workspace/Tabs/WorldTab.cs | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/Ktisis/Interface/Windows/Workspace/Tabs/WorldTab.cs b/Ktisis/Interface/Windows/Workspace/Tabs/WorldTab.cs index d34f455e0..57d63c58b 100644 --- a/Ktisis/Interface/Windows/Workspace/Tabs/WorldTab.cs +++ b/Ktisis/Interface/Windows/Workspace/Tabs/WorldTab.cs @@ -4,8 +4,6 @@ using System.Collections.Generic; using System.Linq; -using Dalamud.Logging; - using FFXIVClientStructs.FFXIV.Client.Graphics.Environment; using ImGuiNET; @@ -159,18 +157,16 @@ private static bool DrawWeatherSelect(int current, out int clickedId) { private static void DrawWeatherLabel(WeatherInfo weather, bool adjustPad = false) { var style = ImGui.GetStyle(); var height = ImGui.GetFrameHeight(); - - //if (weather.Icon != null) { - ImGui.SameLine(0, 0); - ImGui.SetCursorPosX(ImGui.GetCursorStartPos().X + style.ItemInnerSpacing.X); + + ImGui.SameLine(0, 0); + ImGui.SetCursorPosX(ImGui.GetCursorStartPos().X + style.ItemInnerSpacing.X); - var posY = ImGui.GetCursorPos().Y + height / 2 - WeatherIconSize.Y / 2; - if (adjustPad) posY -= style.FramePadding.Y; - ImGui.SetCursorPosY(posY); + var posY = ImGui.GetCursorPos().Y + height / 2 - WeatherIconSize.Y / 2; + if (adjustPad) posY -= style.FramePadding.Y; + ImGui.SetCursorPosY(posY); - ImGui.Image(weather.Icon?.GetWrapOrEmpty().ImGuiHandle ?? 0, WeatherIconSize); - ImGui.SameLine(); - //} + ImGui.Image(weather.Icon?.GetWrapOrEmpty().ImGuiHandle ?? 0, WeatherIconSize); + ImGui.SameLine(); ImGui.Text(weather.Name); } From 84c40e8dab37f5948c47a9c69de8cb84056f6fa3 Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Sat, 6 Jul 2024 22:24:25 +0100 Subject: [PATCH 11/23] more stable proj matrix --- Ktisis/Structs/Extensions/Camera.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ktisis/Structs/Extensions/Camera.cs b/Ktisis/Structs/Extensions/Camera.cs index e2fa6d462..35a60ae22 100644 --- a/Ktisis/Structs/Extensions/Camera.cs +++ b/Ktisis/Structs/Extensions/Camera.cs @@ -9,7 +9,7 @@ public unsafe static Matrix4x4 GetProjectionMatrix(this GameCamera camera) { var cam = camera.CameraBase.SceneCamera.RenderCamera; var proj = cam->ProjectionMatrix; var clip = cam->FarPlane / (cam->FarPlane - cam->NearPlane); - proj.M43 = -(clip * cam->NearPlane); + //proj.M43 = -(clip * cam->NearPlane); proj.M33 = -clip; return proj; } From 16e567f94fad0411ae037fe53a40ba725543d2c3 Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Sat, 6 Jul 2024 22:31:36 +0100 Subject: [PATCH 12/23] categorize bones --- Ktisis/Structs/Bones/Category.cs | 113 +++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 36 deletions(-) diff --git a/Ktisis/Structs/Bones/Category.cs b/Ktisis/Structs/Bones/Category.cs index b457dac7b..99af8a16d 100644 --- a/Ktisis/Structs/Bones/Category.cs +++ b/Ktisis/Structs/Bones/Category.cs @@ -126,49 +126,90 @@ static Category() "n_hkata_l", // ShoulderLeft "n_hkata_r", // ShoulderRight "n_hhiji_l", // ElbowLeft - "n_hhiji_r" // ElbowRight - }); - CreateCategory("head", new Vector4(0.0F, 1.0F, 0.0F, 0.5647059F), new List { + "n_hhiji_r", // ElbowRight "j_kao", // RootHead - "j_ago", // Jaw - "j_f_dmab_l", // EyelidLowerLeft - "j_f_dmab_r", // EyelidLowerRight + "j_ago" // Jaw + }); + + CreateCategory("eyes", new Vector4(0.0F, 1.0F, 0.0F, 0.5647059F), new List() { "j_f_eye_l", // EyeLeft "j_f_eye_r", // EyeRight + "j_f_mab_l", + "j_f_eyepuru_l", + "j_f_mabdn_01_l", + "j_f_mabup_01_l", + "j_f_mabdn_02out_l", + "j_f_mabdn_03in_l", + "j_f_mabup_02out_l", + "j_f_mabup_03in_l", + "j_f_mab_r", + "j_f_eyepuru_r", + "j_f_mabdn_01_r", + "j_f_mabup_01_r", + "j_f_mabdn_02out_r", + "j_f_mabdn_03in_r", + "j_f_mabup_02out_r", + "j_f_mabup_03in_r", + "j_f_mmayu_l", + "j_f_miken_01_l", + "j_f_miken_02_l", + "j_f_mmayu_r", + "j_f_miken_01_r", + "j_f_miken_02_r", + "j_f_mayu_l", // EyebrowLeft + "j_f_mayu_r", // EyebrowRight + }); + + CreateCategory("mouth", new Vector4(0.0F, 1.0F, 0.0F, 0.5647059F), new List() { + "j_f_ago", + "j_f_dago", + "j_f_hagukiup", + "j_f_hagukidn", + "j_f_bero_01", + "j_f_bero_02", + "j_f_bero_03", + "j_f_lip_l", // LipsLeft + "j_f_lip_r", // LipsRight + "j_f_dmlip_01_l", + "j_f_dmlip_02_l", + "j_f_umlip_01_l", + "j_f_umlip_02_l", + "j_f_dmlip_01_r", + "j_f_dmlip_02_r", + "j_f_umlip_01_r", + "j_f_umlip_02_r", + "j_f_dlip_01_l", + "j_f_dlip_02_l", + "j_f_ulip_01_l", + "j_f_ulip_02_l", + "j_f_dlip_01_r", + "j_f_dlip_02_r", + "j_f_ulip_01_r", + "j_f_ulip_02_r", + "j_f_uslip_l", + "j_f_dslip_l", + "j_f_uslip_r", + "j_f_dslip_r" + }); + + CreateCategory("face", new Vector4(0.0F, 1.0F, 0.0F, 0.5647059F), new List() { + "j_f_face", "j_f_hana", // Nose + "j_f_hana_l", + "j_f_hana_r", + "j_f_uhana", "j_f_hoho_l", // CheekLeft "j_f_hoho_r", // CheekRight - "j_f_lip_l", // LipsLeft - "j_f_lip_r", // LipsRight - "j_f_mayu_l", // EyebrowLeft - "j_f_mayu_r", // EyebrowRight - "j_f_memoto", // Bridge - "j_f_miken_l", // BrowLeft - "j_f_miken_r", // BrowRight - "j_f_ulip_a", // LipUpperA - "j_f_umab_l", // EyelidUpperLeft - "j_f_umab_r", // EyelidUpperRight - "j_f_dlip_a", // LipLowerA - "j_f_ulip_b", // LipUpperB - "j_f_dlip_b", // LipLowerB - // Hrothgar Faces - "j_f_hige_l", // HrothWhiskersLeft - "j_f_hige_r", // HrothWhiskersRight - //"j_f_mayu_l", // HrothEyebrowLeft - //"j_f_mayu_r", // HrothEyebrowRight - //"j_f_memoto", // HrothBridge - //"j_f_miken_l", // HrothBrowLeft - //"j_f_miken_r", // HrothBrowRight - "j_f_uago", // HrothJawUpper - "j_f_ulip", // HrothLipUpper - //"j_f_umab_l", // HrothEyelidUpperLeft - //"j_f_umab_r", // HrothEyelidUpperRight - "n_f_lip_l", // HrothLipsLeft - "n_f_lip_r", // HrothLipsRight - "n_f_ulip_l", // HrothLipUpperLeft - "n_f_ulip_r", // HrothLipUpperRight - "j_f_dlip", // HrothLipLower + "j_f_dhoho_l", + "j_f_dhoho_r", + "j_f_shoho_l", + "j_f_shoho_r", + "j_f_dmemoto_l", + "j_f_dmemoto_r", + "j_f_dmiken_l", + "j_f_dmiken_r" }); + CreateCategory("hair", new Vector4(0.0F, 0.0F, 1.0F, 0.5647059F), new List { "j_kami_a", // HairA "j_kami_f_l", // HairFrontLeft From 6a055f8650699ccdcce73391ce5c58d55135ce28 Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Sat, 6 Jul 2024 22:45:46 +0100 Subject: [PATCH 13/23] correct clipping plane calculations --- Ktisis/Structs/Extensions/Camera.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Ktisis/Structs/Extensions/Camera.cs b/Ktisis/Structs/Extensions/Camera.cs index 35a60ae22..6b40917f5 100644 --- a/Ktisis/Structs/Extensions/Camera.cs +++ b/Ktisis/Structs/Extensions/Camera.cs @@ -8,9 +8,13 @@ public static class Camera { public unsafe static Matrix4x4 GetProjectionMatrix(this GameCamera camera) { var cam = camera.CameraBase.SceneCamera.RenderCamera; var proj = cam->ProjectionMatrix; - var clip = cam->FarPlane / (cam->FarPlane - cam->NearPlane); - //proj.M43 = -(clip * cam->NearPlane); - proj.M33 = -clip; + + var far = cam->FarPlane; + var near = cam->NearPlane; + var clip = far / (far - near); + proj.M43 = -(clip * near); + proj.M33 = -((far + near) / (far - near)); + return proj; } public unsafe static Matrix4x4 GetViewMatrix(this GameCamera camera) { From 417c2597127b5e8e57898f20f38e9c71eba7754c Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Sat, 6 Jul 2024 23:43:09 +0100 Subject: [PATCH 14/23] name bones --- Ktisis/Locale/i18n/English.json | 78 +++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 4 deletions(-) diff --git a/Ktisis/Locale/i18n/English.json b/Ktisis/Locale/i18n/English.json index e46f10924..ad6b733db 100644 --- a/Ktisis/Locale/i18n/English.json +++ b/Ktisis/Locale/i18n/English.json @@ -214,12 +214,8 @@ "j_f_eye_l": "Left Eye", "j_f_eye_r": "Right Eye", "j_f_hana": "Nose", - "j_f_hoho_l": "Left Cheek", - "j_f_hoho_r": "Right Cheek", "j_f_lip_l": "Left Lips", "j_f_lip_r": "Right Lips", - "j_f_mayu_l": "Left Eyebrow", - "j_f_mayu_r": "Right Eyebrow", "j_f_memoto": "Bridge", "j_f_miken_l": "Left Brow", "j_f_miken_r": "Right Brow", @@ -259,12 +255,86 @@ "oh_n_hara": "Off Hand", "j_half_l": "Left Half", "j_half_r": "Right Half", + + "j_f_ago": "Jaw", + "j_f_dago": "Lower Jaw", + "j_f_bero_01": "Tongue A", + "j_f_bero_02": "Tongue B", + "j_f_bero_03": "Tongue C", + "j_f_hagukiup": "Upper Teeth", + "j_f_hagukidn": "Lower Teeth", + "j_f_dlip_01_l": "Lip Lower Left Center A", + "j_f_dlip_02_l": "Lip Lower Left Center B", + "j_f_dlip_01_r": "Lip Lower Right Center A", + "j_f_dlip_02_r": "Lip Lower Right Center B", + "j_f_ulip_01_l": "Lip Upper Left Center A", + "j_f_ulip_02_l": "Lip Upper Left Center B", + "j_f_ulip_01_r": "Lip Upper Right Center A", + "j_f_ulip_02_r": "Lip Upper Right Center B", + "j_f_dmlip_01_l": "Lip Lower Left A", + "j_f_dmlip_02_l": "Lip Lower Left B", + "j_f_dmlip_01_r": "Lip Lower Right A", + "j_f_dmlip_02_r": "Lip Lower Right B", + "j_f_umlip_01_l": "Lip Upper Left A", + "j_f_umlip_02_l": "Lip Upper Left B", + "j_f_umlip_01_r": "Lip Upper Right A", + "j_f_umlip_02_r": "Lip Upper Right B", + "j_f_uslip_l": "Lip Upper Left Corner A", + "j_f_dslip_l": "Lip Lower Left Corner A", + "j_f_uslip_r": "Lip Upper Right Corner A", + "j_f_dslip_r": "Lip Lower Right Corner A", + + "j_f_mab_l": "Left Eye Socket", + "j_f_mab_r": "Right Eye Socket", + "j_f_eyepuru_l": "Left Iris", + "j_f_eyepuru_r": "Right Iris", + "j_f_mabup_01_l": "Left Upper Eyelid", + "j_f_mabdn_01_l": "Left Lower Eyelid", + "j_f_mabup_01_r": "Right Upper Eyelid", + "j_f_mabdn_01_r": "Right Lower Eyelid", + "j_f_mabup_02out_l": "Left Upper Eyelid Outer", + "j_f_mabdn_02out_l": "Left Lower Eyelid Outer", + "j_f_mabup_03in_l": "Left Upper Eyelid Inner", + "j_f_mabdn_03in_l": "Left Lower Eyelid Inner", + "j_f_mabup_02out_r": "Right Upper Eyelid Outer", + "j_f_mabdn_02out_r": "Right Lower Eyelid Outer", + "j_f_mabup_03in_r": "Right Upper Eyelid Inner", + "j_f_mabdn_03in_r": "Right Lower Eyelid Inner", + + "j_f_mayu_l": "Left Eyebrow A", + "j_f_mayu_r": "Right Eyebrow A", + "j_f_mmayu_l": "Left Eyebrow B", + "j_f_mmayu_r": "Right Eyebrow B", + "j_f_miken_01_l": "Left Brow Ridge A", + "j_f_miken_02_l": "Left Brow Ridge B", + "j_f_miken_01_r": "Right Brow Ridge A", + "j_f_miken_02_r": "Right Brow Ridge B", + + "j_f_face": "Face", + "j_f_hoho_l": "Left Cheek", + "j_f_hoho_r": "Right Cheek", + "j_f_dhoho_l": "Left Outer Cheek", + "j_f_dhoho_r": "Right Outer Cheek", + "j_f_shoho_l": "Left Middle Cheek", + "j_f_shoho_r": "Right Middle Cheek", + "j_f_dmemoto_l": "Left Inner Cheek", + "j_f_dmemoto_r": "Right Inner Cheek", + "j_f_uhana": "Bridge", + "j_f_hana_l": "Left Nostril", + "j_f_hana_r": "Right Nostril", + "j_f_dmiken_l": "Left Glabella", + "j_f_dmiken_r": "Right Glabella", + + "j_ex_met_vb": "Visor", // Bone Category names "other": "Other", "body": "Body", "head": "Head", "hair": "Hair", + "eyes": "Eyes", + "face": "Face", + "mouth": "Mouth", "clothes": "Clothes", "weapons": "Weapons", "right hand": "Right hand", From 191d5444cc3e6cb9fd3f3eb5afda8c0bb5b160f6 Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Sun, 7 Jul 2024 00:10:40 +0100 Subject: [PATCH 15/23] correct drawdata customize offset --- Ktisis/Structs/Actor/ActorDrawData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ktisis/Structs/Actor/ActorDrawData.cs b/Ktisis/Structs/Actor/ActorDrawData.cs index 096fb8038..14335fd62 100644 --- a/Ktisis/Structs/Actor/ActorDrawData.cs +++ b/Ktisis/Structs/Actor/ActorDrawData.cs @@ -8,7 +8,7 @@ public struct ActorDrawData { [FieldOffset(0x0F0)] public Weapon Prop; [FieldOffset(0x160)] public Equipment Equipment; - [FieldOffset(0x188)] public Customize Customize; + [FieldOffset(0x1B0)] public Customize Customize; [FieldOffset(0x1D0)] public ushort Glasses; } From 7ff89db0f577dc7772d2ab0b0ad10b5c8113cb62 Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Sun, 7 Jul 2024 16:16:21 +0100 Subject: [PATCH 16/23] Hook camera pre-update --- Ktisis/Interop/Hooks/CameraHooks.cs | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/Ktisis/Interop/Hooks/CameraHooks.cs b/Ktisis/Interop/Hooks/CameraHooks.cs index ac0381f1c..b4ee392d9 100644 --- a/Ktisis/Interop/Hooks/CameraHooks.cs +++ b/Ktisis/Interop/Hooks/CameraHooks.cs @@ -2,7 +2,6 @@ using System.Runtime.InteropServices; using Dalamud.Hooking; -using Dalamud.Logging; using FFXIVClientStructs.FFXIV.Common.Math; using GameCamera = FFXIVClientStructs.FFXIV.Client.Game.Camera; @@ -39,9 +38,9 @@ private unsafe static void EndOverride() { // Camera control - private delegate nint ControlDelegate(nint a1); + private delegate bool ControlDelegate(nint a1); private static Hook ControlHook = null!; - private unsafe static nint ControlDetour(nint a1) { + private unsafe static bool ControlDetour(nint a1) { StartOverride(); var exec = ControlHook.Original(a1); EndOverride(); @@ -65,6 +64,17 @@ private unsafe static nint ControlDetour(nint a1) { return exec; } + // Pre-update + + private delegate nint PreUpdateDelegate(nint a1); + private static Hook PreUpdateHook = null!; + private unsafe static nint PreUpdateDetour(nint a1) { + StartOverride(); + var exec = PreUpdateHook.Original(a1); + EndOverride(); + return exec; + } + // Freecam private unsafe delegate Matrix4x4* CalcViewMatrixDelegate(SceneCamera* camera); @@ -163,6 +173,7 @@ internal static void SetEnabled(bool enabled) { private static void EnableHooks() { TargetHook.Enable(); ControlHook.Enable(); + PreUpdateHook.Enable(); ActiveCamHook.Enable(); CameraEventHook.Enable(); CameraUiHook.Enable(); @@ -174,6 +185,7 @@ private static void EnableHooks() { private static void DisableHooks() { TargetHook.Disable(); ControlHook.Disable(); + PreUpdateHook.Disable(); ActiveCamHook.Disable(); CameraEventHook.Disable(); CameraUiHook.Disable(); @@ -194,8 +206,11 @@ internal unsafe static void Init() { var camCtrlAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 48 83 3D ?? ?? ?? ?? ?? 74 0C"); ControlHook = Services.Hooking.HookFromAddress(camCtrlAddr, ControlDetour); + + var preUpdateAddr = Services.SigScanner.ScanText("48 83 EC 28 8B 41 48"); + PreUpdateHook = Services.Hooking.HookFromAddress(preUpdateAddr, PreUpdateDetour); - var actCamAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? F7 80"); + var actCamAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 41 0F B6 DF"); ActiveCamHook = Services.Hooking.HookFromAddress(actCamAddr, GetActiveCamDetour); var camEventAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 0F B6 F8 EB 34"); From 4d174ad2575fd4bbdda193c57a643ead69e514a9 Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Sun, 7 Jul 2024 16:49:09 +0100 Subject: [PATCH 17/23] fix freecam --- Ktisis/Interop/Hooks/CameraHooks.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Ktisis/Interop/Hooks/CameraHooks.cs b/Ktisis/Interop/Hooks/CameraHooks.cs index b4ee392d9..2d81e3413 100644 --- a/Ktisis/Interop/Hooks/CameraHooks.cs +++ b/Ktisis/Interop/Hooks/CameraHooks.cs @@ -6,6 +6,7 @@ using FFXIVClientStructs.FFXIV.Common.Math; using GameCamera = FFXIVClientStructs.FFXIV.Client.Game.Camera; using SceneCamera = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.Camera; +using RenderCamera = FFXIVClientStructs.FFXIV.Client.Graphics.Render.Camera; using Ktisis.Camera; using Ktisis.Structs.FFXIV; @@ -77,11 +78,17 @@ private unsafe static nint PreUpdateDetour(nint a1) { // Freecam + private unsafe delegate Matrix4x4* LoadMatrixDelegate(RenderCamera* camera, Matrix4x4* matrix, int a3, int a4); + private static LoadMatrixDelegate LoadMatrix = null!; + private unsafe delegate Matrix4x4* CalcViewMatrixDelegate(SceneCamera* camera); private static Hook CalcViewMatrixHook = null!; private unsafe static Matrix4x4* CalcViewMatrixDetour(SceneCamera* camera) { + var exec = CalcViewMatrixHook.Original(camera); + var freecam = CameraService.GetFreecam(); - if (freecam == null || freecam.WorkCamera == null) goto retn; + if (freecam == null || freecam.WorkCamera == null) + return exec; try { var active = Services.Camera->GetActiveCamera(); @@ -92,14 +99,14 @@ private unsafe static nint PreUpdateDetour(nint a1) { var matrix = freecam.WorkCamera.Update(active->FoV * Math.Abs(1 + zoom)); *tarMatrix = matrix; - return tarMatrix; + LoadMatrix(camera->RenderCamera, tarMatrix, 0, 0); } } catch (Exception e) { Ktisis.Log.Error(e.ToString()); DisableHooks(); } - retn: return CalcViewMatrixHook.Original(camera); + return exec; } // GetActiveCamera @@ -224,6 +231,9 @@ internal unsafe static void Init() { var viewMxAddr = Services.SigScanner.ScanText("48 89 5C 24 ?? 57 48 81 EC ?? ?? ?? ?? F6 81 ?? ?? ?? ?? ?? 48 8B D9 48 89 B4 24 ?? ?? ?? ??"); CalcViewMatrixHook = Services.Hooking.HookFromAddress(viewMxAddr, CalcViewMatrixDetour); + + var loadMxAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 48 8B 17 48 8D 4D E0"); + LoadMatrix = Marshal.GetDelegateForFunctionPointer(loadMxAddr); var collideAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 4C 8B AC 24 ?? ?? ?? ?? 32 DB"); CameraCollisionHook = Services.Hooking.HookFromAddress(collideAddr, CameraCollisionDetour); @@ -232,6 +242,7 @@ internal unsafe static void Init() { internal static void Dispose() { DisableHooks(); ControlHook.Dispose(); + PreUpdateHook.Dispose(); ActiveCamHook.Dispose(); CameraEventHook.Dispose(); CameraUiHook.Dispose(); From 361e36c65ca76d947d849867212f3f7cef75a240 Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Sun, 7 Jul 2024 18:00:16 +0100 Subject: [PATCH 18/23] Rework click target hooks --- Ktisis/Interop/Hooks/EventsHooks.cs | 93 ++++++++++++----------------- 1 file changed, 39 insertions(+), 54 deletions(-) diff --git a/Ktisis/Interop/Hooks/EventsHooks.cs b/Ktisis/Interop/Hooks/EventsHooks.cs index 1cef958f0..0a1bd7fdf 100644 --- a/Ktisis/Interop/Hooks/EventsHooks.cs +++ b/Ktisis/Interop/Hooks/EventsHooks.cs @@ -4,10 +4,12 @@ using Dalamud.Hooking; +using FFXIVClientStructs.FFXIV.Client.Game.Control; using FFXIVClientStructs.FFXIV.Client.System.Framework; using FFXIVClientStructs.FFXIV.Client.UI.Agent; using FFXIVClientStructs.FFXIV.Component.GUI; +using Ktisis.Events; using Ktisis.Structs.Actor.Equip; using Ktisis.Structs.Actor.Equip.SetSources; @@ -20,8 +22,9 @@ public static void Init() { var MiragePrismMiragePlate = Services.AddonManager.Get(); MiragePrismMiragePlate.ReceiveEvent += OnGlamourPlatesReceiveEvent; - - OnGposeEnter(); // TODO: move this call on "enter gpose" event + + EventManager.OnGPoseChange += OnGposeChange; + OnLogin(); } @@ -33,7 +36,8 @@ public static void Dispose() { var MiragePrismMiragePlate = Services.AddonManager.Get(); MiragePrismMiragePlate.ReceiveEvent -= OnGlamourPlatesReceiveEvent; - OnGposeLeave(); + EventManager.OnGPoseChange -= OnGposeChange; + OnLogout(); } @@ -44,13 +48,20 @@ private static void OnLogin() { private static void OnLogout() { Sets.Dispose(); } + + private static void OnGposeChange(bool state) { + if (state) + OnGposeEnter(); + else + OnGposeLeave(); + } private static void OnGposeEnter() { var ClickTargetAddon = Services.AddonManager.Get(); ClickTargetAddon.Enable(); } private static void OnGposeLeave() { var ClickTargetAddon = Services.AddonManager.Get(); - ClickTargetAddon.Dispose(); + ClickTargetAddon.Disable(); } private static unsafe void OnGlamourPlatesReceiveEvent(object? sender, ReceiveEventArgs e) { @@ -118,68 +129,42 @@ public void Dispose() { } } internal unsafe class ClickTargetAddon : IDisposable { - - - private delegate IntPtr ClickTarget(IntPtr a1, byte* a2, byte a3); - private readonly Hook? rightClickTargetHook; - private readonly Hook? leftClickTargetHook; + private delegate nint ProcessMouseStateDelegate(TargetSystem* targets, nint a2, nint a3); + private readonly Hook? ProcessMouseStateHook; public ClickTargetAddon() { - // TODO - //rightClickTargetHook ??= Services.Hooking.HookFromAddress(Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 48 8B CE E8 ?? ?? ?? ?? 48 85 C0 74 1B"), RightClickTargetDetour); - //leftClickTargetHook ??= Services.Hooking.HookFromAddress(Services.SigScanner.ScanText("E8 ?? ?? ?? ?? BA ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 84 C0 74 16"), LeftClickTargetDetour); + var addr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 4C 8B BC 24 ?? ?? ?? ?? 4C 8B B4 24 ?? ?? ?? ?? 48 8B B4 24 ?? ?? ?? ?? 48 8B 9C 24 ?? ?? ?? ??"); + ProcessMouseStateHook = Services.Hooking.HookFromAddress(addr, ProcessMouseStateDetour); } - public void Enable() { - //rightClickTargetHook?.Enable(); - //leftClickTargetHook?.Enable(); - } + private nint ProcessMouseStateDetour(TargetSystem* targets, nint a2, nint a3) { + var prev = targets->GPoseTarget; + var exec = ProcessMouseStateHook!.Original(targets, a2, a3); - public void Dispose() { - return; - - // Verify presence of hooks, in case of calls when it's already been disposed - if (!(bool)rightClickTargetHook?.IsDisposed!) { - if ((bool)rightClickTargetHook?.IsEnabled!) - rightClickTargetHook?.Disable(); - rightClickTargetHook?.Dispose(); - } - if (!(bool)leftClickTargetHook?.IsDisposed!) { - if ((bool)leftClickTargetHook?.IsEnabled!) - leftClickTargetHook?.Disable(); - leftClickTargetHook?.Dispose(); + if (Ktisis.IsInGPose && targets->GPoseTarget != prev) { + var left = Ktisis.Configuration.DisableChangeTargetOnLeftClick && exec == 0; + var right = !left && Ktisis.Configuration.DisableChangeTargetOnRightClick && exec == 0x10; + if (left || right) targets->GPoseTarget = prev; } + + return exec; } + public void Enable() { + ProcessMouseStateHook?.Enable(); + } - private IntPtr RightClickTargetDetour(IntPtr a1, byte* a2, byte a3) => - ClickEvent(a1, a2, a3, ClickType.Right); - private IntPtr LeftClickTargetDetour(IntPtr a1, byte* a2, byte a3) => - ClickEvent(a1, a2, a3, ClickType.Left); - - - private IntPtr ClickEvent(IntPtr a1, byte* actor, byte a3, ClickType clickType) { - if (Ktisis.IsInGPose) { - // 1. Prevents target self when clicking somewhere else with left click - // 2. Prevent target change with left and right clicks - // returning null wasn't enough for 1. so we pass the current target instead - - var left = Ktisis.Configuration.DisableChangeTargetOnLeftClick && clickType == ClickType.Left; - var right = Ktisis.Configuration.DisableChangeTargetOnRightClick && clickType == ClickType.Right; + public void Disable() { + ProcessMouseStateHook?.Disable(); + } - if (left || right) - return IntPtr.Zero; + public void Dispose() { + if (ProcessMouseStateHook?.IsDisposed == false) { + ProcessMouseStateHook?.Disable(); + ProcessMouseStateHook?.Dispose(); } - - if (clickType == ClickType.Left) return leftClickTargetHook!.Original(a1, actor, a3); - if (clickType == ClickType.Right) return rightClickTargetHook!.Original(a1, actor, a3); - - return IntPtr.Zero; - } - internal enum ClickType { - Left, - Right } + } internal unsafe class ReceiveEventArgs : EventArgs { public ReceiveEventArgs(AgentInterface* agentInterface, void* rawData, AtkValue* eventArgs, uint eventArgsCount, ulong senderID) { From 3ab7ce1800144e89cfd7820a51724b7d3268a81e Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Sun, 7 Jul 2024 18:06:50 +0100 Subject: [PATCH 19/23] update hat toggle --- Ktisis/Structs/Actor/Actor.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Ktisis/Structs/Actor/Actor.cs b/Ktisis/Structs/Actor/Actor.cs index 14ee43dd8..e6c2b1bd9 100644 --- a/Ktisis/Structs/Actor/Actor.cs +++ b/Ktisis/Structs/Actor/Actor.cs @@ -22,7 +22,7 @@ public struct Actor { [FieldOffset(0x708)] public ActorDrawData DrawData; - [FieldOffset(0x89E)] public bool IsHatHidden; + [FieldOffset(0x8D6)] public bool IsHatHidden; public const int GazeOffset = 0xD00; [FieldOffset(GazeOffset + 0x10)] public ActorGaze Gaze; @@ -58,8 +58,11 @@ public unsafe void LookAt(Gaze* tar, GazeControl bodyPart) { // Change equipment - no redraw method - public unsafe ItemEquip GetEquip(EquipIndex index) - => this.Model != null ? this.Model->GetEquipSlot((int)index) : default; + public unsafe ItemEquip GetEquip(EquipIndex index) { + if (index == EquipIndex.Head && this.IsHatHidden) + return this.DrawData.Equipment.Head; + return this.Model != null ? this.Model->GetEquipSlot((int)index) : default; + } public unsafe Customize GetCustomize() => this.Model != null ? this.Model->GetCustomize() ?? default : default; From 1f6aa37eb3090f4d75134cfc34e674953847c4d5 Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Sun, 7 Jul 2024 18:49:08 +0100 Subject: [PATCH 20/23] correct DemiEquip offset --- Ktisis/Structs/Actor/ActorModel.cs | 2 +- Ktisis/Structs/Actor/Weapon.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Ktisis/Structs/Actor/ActorModel.cs b/Ktisis/Structs/Actor/ActorModel.cs index 45b9250d5..df2e7faea 100644 --- a/Ktisis/Structs/Actor/ActorModel.cs +++ b/Ktisis/Structs/Actor/ActorModel.cs @@ -32,7 +32,7 @@ public struct ActorModel { [FieldOffset(0x9D0)] public Customize Customize; - [FieldOffset(0x918)] public unsafe fixed ulong DemiEquip[5]; + [FieldOffset(0x9D8)] public unsafe fixed ulong DemiEquip[5]; [FieldOffset(0x9F0)] public unsafe fixed ulong HumanEquip[11]; [FieldOffset(0x2E0)] public float WeatherWetness; // Set to 1.0f when raining and not covered or umbrella'd diff --git a/Ktisis/Structs/Actor/Weapon.cs b/Ktisis/Structs/Actor/Weapon.cs index cb5f14e97..c5181fd98 100644 --- a/Ktisis/Structs/Actor/Weapon.cs +++ b/Ktisis/Structs/Actor/Weapon.cs @@ -24,7 +24,7 @@ public unsafe void SetEquip(WeaponEquip item) { } } - [StructLayout(LayoutKind.Explicit)] + [StructLayout(LayoutKind.Explicit, Size = 0x8)] public struct WeaponEquip : IEquipItem { [FieldOffset(0x00)] public ushort Set; [FieldOffset(0x02)] public ushort Base; From cc471f4595b40b191cbfdab3b95332d53d4ce453 Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Sun, 7 Jul 2024 18:52:31 +0100 Subject: [PATCH 21/23] Update GLib --- GLib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GLib b/GLib index 749ba611d..5d0018cc3 160000 --- a/GLib +++ b/GLib @@ -1 +1 @@ -Subproject commit 749ba611ded0d845c1977771f048fda7c342b539 +Subproject commit 5d0018cc300284651ba1498d7e52e151a86b6017 From db94fe4c5d2ec61b8854baaa06758a7381a55876 Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Sun, 7 Jul 2024 18:56:04 +0100 Subject: [PATCH 22/23] bump API level + assembly version --- Ktisis/Ktisis.csproj | 2 +- Ktisis/Ktisis.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Ktisis/Ktisis.csproj b/Ktisis/Ktisis.csproj index 27215d773..2e01fe63d 100644 --- a/Ktisis/Ktisis.csproj +++ b/Ktisis/Ktisis.csproj @@ -3,7 +3,7 @@ Chirp Ktisis Tools - 0.2.22 + 0.2.23 An internal posing tool. https://github.com/ktisis-tools/Ktisis Debug;Release;External diff --git a/Ktisis/Ktisis.json b/Ktisis/Ktisis.json index 5ba56e83e..ef988e2bd 100644 --- a/Ktisis/Ktisis.json +++ b/Ktisis/Ktisis.json @@ -6,9 +6,9 @@ "InternalName": "Ktisis", "RepoUrl": "https://github.com/ktisis-tools/Ktisis", "IconUrl": "https://github.com/ktisis-tools/Ktisis/raw/main/icon.png", - "AssemblyVersion": "0.2.19", + "AssemblyVersion": "0.2.23", "ApplicableVersion": "any", - "DalamudApiLevel": 9, + "DalamudApiLevel": 10, "Tags": [ "gpose", "posing" From ffec0170fc5f6a9eb8eb627ebcb4a07f390375b4 Mon Sep 17 00:00:00 2001 From: chirp <72366111+chirpxiv@users.noreply.github.com> Date: Sun, 7 Jul 2024 19:30:57 +0100 Subject: [PATCH 23/23] hook kinedriver/havok controller --- Ktisis/Interop/Hooks/PoseHooks.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Ktisis/Interop/Hooks/PoseHooks.cs b/Ktisis/Interop/Hooks/PoseHooks.cs index 3da9443d0..fd0d9ec95 100644 --- a/Ktisis/Interop/Hooks/PoseHooks.cs +++ b/Ktisis/Interop/Hooks/PoseHooks.cs @@ -26,6 +26,9 @@ public static class PoseHooks { internal unsafe delegate byte* LookAtIKDelegate(byte* a1, long* a2, long* a3, float a4, long* a5, long* a6); internal static Hook LookAtIKHook = null!; + + internal delegate nint KineDriverDelegate(nint a1, nint a2); + internal static Hook KineDriverHook = null!; internal unsafe delegate byte AnimFrozenDelegate(uint* a1, int a2); internal static Hook AnimFrozenHook = null!; @@ -35,7 +38,7 @@ public static class PoseHooks { internal unsafe delegate char SetSkeletonDelegate(Skeleton* a1, ushort a2, nint a3); internal static Hook SetSkeletonHook = null!; - + internal unsafe delegate nint BustDelegate(ActorModel* a1, Breasts* a2); internal static Hook BustHook = null!; @@ -58,6 +61,9 @@ internal static unsafe void Init() { var lookAtIK = Services.SigScanner.ScanText("48 8B C4 48 89 58 08 48 89 70 10 F3 0F 11 58"); LookAtIKHook = Services.Hooking.HookFromAddress(lookAtIK, LookAtIKDetour); + + var kineDrive = Services.SigScanner.ScanText("48 8B C4 55 57 48 83 EC 58"); + KineDriverHook = Services.Hooking.HookFromAddress(kineDrive, KineDriverDetour); var animFrozen = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 0F B6 F8 84 C0 74 12"); AnimFrozenHook = Services.Hooking.HookFromAddress(animFrozen, AnimFrozenDetour); @@ -79,6 +85,7 @@ internal static void DisablePosing() { SetBoneModelSpaceFfxivHook?.Disable(); SyncModelSpaceHook?.Disable(); LookAtIKHook?.Disable(); + KineDriverHook.Disable(); UpdatePosHook?.Disable(); AnimFrozenHook?.Disable(); BustHook?.Disable(); @@ -91,6 +98,7 @@ internal static void EnablePosing() { SetBoneModelSpaceFfxivHook?.Enable(); SyncModelSpaceHook?.Enable(); LookAtIKHook?.Enable(); + KineDriverHook.Enable(); UpdatePosHook?.Enable(); AnimFrozenHook?.Enable(); BustHook?.Enable(); @@ -211,6 +219,10 @@ private unsafe static nint BustDetour(ActorModel* a1, Breasts* a2) { return (byte*)nint.Zero; } + private static nint KineDriverDetour(nint a1, nint a2) { + return nint.Zero; + } + private unsafe static byte AnimFrozenDetour(uint* a1, int a2) { return 1; } @@ -249,6 +261,8 @@ internal static void Dispose() { SyncModelSpaceHook.Dispose(); LookAtIKHook.Disable(); LookAtIKHook.Dispose(); + KineDriverHook.Disable(); + KineDriverHook.Dispose(); AnimFrozenHook.Disable(); AnimFrozenHook.Dispose(); UpdatePosHook.Disable();