From 80d0ed4f07ea88e69a1e3706c38dae421e5afdcc Mon Sep 17 00:00:00 2001
From: RisaDev <151885272+RisaDev@users.noreply.github.com>
Date: Mon, 30 Sep 2024 22:44:19 +0300
Subject: [PATCH] Expose GameState.GetCutsceneParentIndex and
GameState.SetCutsceneParentIndex via IPC
---
.../Api/CustomizePlusIpc.GameState.cs | 31 ++++++++++++
CustomizePlus/Api/CustomizePlusIpc.cs | 4 ++
CustomizePlus/Api/Enums/ErrorCode.cs | 8 ++++
.../MainWindow/Tabs/Debug/IPCTestTab.cs | 48 +++++++++++++++++++
.../UI/Windows/PopupSystem.Messages.cs | 2 +
5 files changed, 93 insertions(+)
create mode 100644 CustomizePlus/Api/CustomizePlusIpc.GameState.cs
diff --git a/CustomizePlus/Api/CustomizePlusIpc.GameState.cs b/CustomizePlus/Api/CustomizePlusIpc.GameState.cs
new file mode 100644
index 0000000..511b9e5
--- /dev/null
+++ b/CustomizePlus/Api/CustomizePlusIpc.GameState.cs
@@ -0,0 +1,31 @@
+using CustomizePlus.Api.Enums;
+using ECommons.EzIpcManager;
+
+namespace CustomizePlus.Api;
+
+public partial class CustomizePlusIpc
+{
+ ///
+ /// Retrieve parent for actor. If actor has no parent will return -1.
+ /// This IPC method is identical to same method in Penumbra.
+ /// /!\ Generally speaking use cases for this are quite limited and you should not use this unless you know what you are doing.
+ /// Improper use of this method can lead to incorrect Customize+ behavior.
+ ///
+ [EzIPC("GameState.GetCutsceneParentIndex")]
+ private int GetCutsceneParentIndex(int actorIndex)
+ {
+ return _cutsceneService.GetParentIndex(actorIndex);
+ }
+
+ ///
+ /// Set parent for actor.
+ /// This IPC method is identical to same method in Penumbra.
+ /// /!\ Generally speaking use cases for this are quite limited and you should not use this unless you know what you are doing.
+ /// Improper use of this method can lead to incorrect Customize+ behavior.
+ ///
+ [EzIPC("GameState.SetCutsceneParentIndex")]
+ private int SetCutsceneParentIndex(int copyIndex, int newParentIndex)
+ {
+ return _cutsceneService.SetParentIndex(copyIndex, newParentIndex) ? (int)ErrorCode.Success : (int)ErrorCode.InvalidArgument;
+ }
+}
diff --git a/CustomizePlus/Api/CustomizePlusIpc.cs b/CustomizePlus/Api/CustomizePlusIpc.cs
index 8d141f2..6c60887 100644
--- a/CustomizePlus/Api/CustomizePlusIpc.cs
+++ b/CustomizePlus/Api/CustomizePlusIpc.cs
@@ -1,6 +1,7 @@
using CustomizePlus.Armatures.Events;
using CustomizePlus.Core.Services;
using CustomizePlus.Game.Services;
+using CustomizePlus.GameData.Services;
using CustomizePlus.Profiles;
using CustomizePlus.Profiles.Events;
using Dalamud.Plugin;
@@ -25,6 +26,7 @@ public partial class CustomizePlusIpc : IDisposable
private readonly ProfileManager _profileManager;
private readonly GameObjectService _gameObjectService;
private readonly ProfileFileSystem _profileFileSystem;
+ private readonly CutsceneService _cutsceneService;
private readonly ArmatureChanged _armatureChangedEvent;
@@ -40,6 +42,7 @@ public partial class CustomizePlusIpc : IDisposable
ProfileManager profileManager,
GameObjectService gameObjectService,
ProfileFileSystem profileFileSystem,
+ CutsceneService cutsceneService,
ArmatureChanged armatureChangedEvent)
{
_pluginInterface = pluginInterface;
@@ -48,6 +51,7 @@ public partial class CustomizePlusIpc : IDisposable
_profileManager = profileManager;
_gameObjectService = gameObjectService;
_profileFileSystem = profileFileSystem;
+ _cutsceneService = cutsceneService;
_armatureChangedEvent = armatureChangedEvent;
diff --git a/CustomizePlus/Api/Enums/ErrorCode.cs b/CustomizePlus/Api/Enums/ErrorCode.cs
index e4d6b6f..b47c46a 100644
--- a/CustomizePlus/Api/Enums/ErrorCode.cs
+++ b/CustomizePlus/Api/Enums/ErrorCode.cs
@@ -12,18 +12,26 @@ namespace CustomizePlus.Api.Enums;
public enum ErrorCode
{
Success = 0,
+
///
/// Returned when invalid character address was provided
///
InvalidCharacter = 1,
+
///
/// Returned if IPCCharacterProfile could not be deserialized or deserialized into an empty object
///
CorruptedProfile = 2,
+
///
/// Provided character does not have active profiles, provided profile id is invalid or provided profile id is not valid for use in current function
///
ProfileNotFound = 3,
+ ///
+ /// General error telling that one of the provided arguments were invalid.
+ ///
+ InvalidArgument = 4,
+
UnknownError = 255
}
diff --git a/CustomizePlus/UI/Windows/MainWindow/Tabs/Debug/IPCTestTab.cs b/CustomizePlus/UI/Windows/MainWindow/Tabs/Debug/IPCTestTab.cs
index 6bcc7dd..a91cf7f 100644
--- a/CustomizePlus/UI/Windows/MainWindow/Tabs/Debug/IPCTestTab.cs
+++ b/CustomizePlus/UI/Windows/MainWindow/Tabs/Debug/IPCTestTab.cs
@@ -64,6 +64,12 @@ public class IPCTestTab //: IDisposable
[EzIPC("Profile.GetByUniqueId")]
private readonly Func _getProfileByIdIpcFunc;
+ [EzIPC("GameState.GetCutsceneParentIndex")]
+ private readonly Func _getCutsceneParentIdxIpcFunc;
+
+ [EzIPC("GameState.SetCutsceneParentIndex")]
+ private readonly Func _setCutsceneParentIdxIpcFunc;
+
private string? _rememberedProfileJson;
private (int, int) _apiVersion;
@@ -74,6 +80,10 @@ public class IPCTestTab //: IDisposable
private string _targetProfileId = "";
+ private int _cutsceneActorIdx;
+ private int _cutsceneActorParentIdx;
+
+
public IPCTestTab(
IDalamudPluginInterface pluginInterface,
IObjectTable objectTable,
@@ -286,6 +296,44 @@ public class IPCTestTab //: IDisposable
_popupSystem.ShowPopup(PopupSystem.Messages.ActionError);
}
}
+
+ ImGui.Text("Cutscene actor index:");
+ ImGui.SameLine();
+ ImGui.InputInt("##cutsceneactoridx", ref _cutsceneActorIdx);
+
+ ImGui.Text("Cutscene actor parent index:");
+ ImGui.SameLine();
+ ImGui.InputInt("##cutsceneactorparentidx", ref _cutsceneActorParentIdx);
+
+ if (ImGui.Button("GameState.GetCutsceneParentIndex"))
+ {
+ int result = _getCutsceneParentIdxIpcFunc(_cutsceneActorIdx);
+ if (result > -1)
+ {
+ _cutsceneActorParentIdx = result;
+ _popupSystem.ShowPopup(PopupSystem.Messages.IPCSuccessfullyExecuted);
+ }
+ else
+ {
+ _logger.Error($"No parent for actor or actor not found while caling GetCutsceneParentIndex");
+ _popupSystem.ShowPopup(PopupSystem.Messages.ActionError);
+ }
+ }
+
+ if (ImGui.Button("GameState.SetCutsceneParentIndex"))
+ {
+ int result = _setCutsceneParentIdxIpcFunc(_cutsceneActorIdx, _cutsceneActorParentIdx);
+ if (result == 0)
+ {
+ _cutsceneActorParentIdx = result;
+ _popupSystem.ShowPopup(PopupSystem.Messages.IPCSuccessfullyExecuted);
+ }
+ else
+ {
+ _logger.Error($"Error code {result} while calling GameState.SetCutsceneParentIndex");
+ _popupSystem.ShowPopup(PopupSystem.Messages.ActionError);
+ }
+ }
}
[EzIPCEvent("Profile.OnUpdate")]
diff --git a/CustomizePlus/UI/Windows/PopupSystem.Messages.cs b/CustomizePlus/UI/Windows/PopupSystem.Messages.cs
index a968c7f..47c7066 100644
--- a/CustomizePlus/UI/Windows/PopupSystem.Messages.cs
+++ b/CustomizePlus/UI/Windows/PopupSystem.Messages.cs
@@ -15,6 +15,7 @@ public partial class PopupSystem
public const string IPCSetProfileToChrDone = "ipc_set_profile_to_character_done";
public const string IPCRevertDone = "ipc_revert_done";
public const string IPCCopiedToClipboard = "ipc_copied_to clipboard";
+ public const string IPCSuccessfullyExecuted = "ipc_successfully_executed";
public const string IPCEnableProfileByIdDone = "ipc_enable_profile_by_id_done";
public const string IPCDisableProfileByIdDone = "ipc_disable_profile_by_id_done";
@@ -35,6 +36,7 @@ public partial class PopupSystem
RegisterPopup(Messages.IPCSetProfileToChrDone, "SetProfileToCharacter has been called with data from memory, profile id printed to log");
RegisterPopup(Messages.IPCRevertDone, "DeleteTemporaryProfileByUniqueId has been called");
RegisterPopup(Messages.IPCCopiedToClipboard, "Copied into clipboard");
+ RegisterPopup(Messages.IPCSuccessfullyExecuted, "Successfully executed");
RegisterPopup(Messages.IPCEnableProfileByIdDone, "Enable profile by id has been called");
RegisterPopup(Messages.IPCDisableProfileByIdDone, "Disable profile by id has been called");