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");