diff --git a/.vscode/tasks.json b/.vscode/tasks.json index fa7b2b7..8b3ca82 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -7,9 +7,14 @@ "type": "process", "args": [ "build", - "E:/modding/ExtendedConversations/src/ExtendedConversations.csproj" + "E:/Modding/BattleTech/ExtendedConversations/src/ExtendedConversations.csproj" ], "problemMatcher": "$msCompile" + }, + { + "label": "copy (assets)", + "type": "shell", + "command": "./copy-assets.sh" } ] } \ No newline at end of file diff --git a/README.md b/README.md index 2f8a914..647b7bc 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,8 @@ Dialog tags allow you to inject data into your dialog text. - `Set Characters Visible` - This allows you to show and hide characters in the dropship. You specify the characters in a comma separated list. - `Add Contract` - This allows you to add a contract to the contracts list in the XOs room. - `Add Flashpoint` - This allows you to add a flashpoint to the starmap. See [usage instructions](https://github.com/CWolfs/ExtendedConversations/issues/44#issuecomment-1335134292). +- `Set BattleTech Camera Hard Lock` - This has one advantage over the vanilla `Set BattleTech Camera Lock`. It is useful in 1-on-1 conversations and letting other characters talk without transitioning away. The vanilla lock doesn't work for 1-on-1 conversations. +- `Sideload Conversation` - This loads another conversation into the current active conversation. It's seamless so you it feels like it's the same conversation. It can enter the new conversation at a specific node and can also return to the original conversation if enabled. **Important: It's recommended you use this on Response nodes, but you can use it on Prompt nodes too. When using on Prompt nodes conditionals for the following responses at that specific level might not work**. ### Value Getters diff --git a/copy-assets.sh b/copy-assets.sh new file mode 100644 index 0000000..7695019 --- /dev/null +++ b/copy-assets.sh @@ -0,0 +1,4 @@ +#!/bin/bash +cp -r 'mod.json' 'D:/Program Files (x86)/Steam/steamapps/common/BATTLETECH/Mods/ExtendedConversations' +cp -r 'src/bin/Debug/net471/ExtendedConversations.dll' 'D:/Program Files (x86)/Steam/steamapps/common/BATTLETECH/Mods/ExtendedConversations' +cp -r 'src/bin/Debug/net471/ExtendedConversations.pdb' 'D:/Program Files (x86)/Steam/steamapps/common/BATTLETECH/Mods/ExtendedConversations' \ No newline at end of file diff --git a/mod.json b/mod.json index 659aec9..b3fb5bc 100644 --- a/mod.json +++ b/mod.json @@ -2,7 +2,7 @@ "Name": "ExtendedConversations", "Enabled": true, - "Version": "0.4.5", + "Version": "0.5.0", "Description": "Extended Conversations is a utility mod to provide more conversation conditions, actions and other functionality", "Author": "CWolf", "Website": "https://github.com/CWolfs/ExtendedConversations/", diff --git a/operations/set_battletech_camera_hard_lock.json b/operations/set_battletech_camera_hard_lock.json new file mode 100644 index 0000000..65a93d2 --- /dev/null +++ b/operations/set_battletech_camera_hard_lock.json @@ -0,0 +1,35 @@ +{ + "key": "Set BattleTech Camera Hard Lock", + "label": "Hard lock the camera to", + "view": ["label", "inputs"], + "scope": "action", + "category": "primary", + "tooltip": "This will ensure only the set lock target is shown. Mainly useful for 1-on-1 conversations and having the non-main character talk but the camera stay focused on the main character.", + "inputs": [ + { + "label": "Key", + "types": ["string"], + "values": [ + { "text": "AUTO", "value": "AUTO" }, + { "text": "Alexander", "value": "ALEXANDER" }, + { "text": "Darius", "value": "DARIUS" }, + { "text": "Farah", "value": "FARAH" }, + { "text": "Kamea", "value": "KAMEA" }, + { "text": "Sumire", "value": "SUMIRE" }, + { "text": "Yang", "value": "YANG" }, + { "text": "Monitor", "value": "MONITOR" }, + { "text": "Navscreen", "value": "NAVSCREEN" }, + { "text": "Default", "value": "DEFAULT" }, + { "text": "Contracts", "value": "CONTRACTS" }, + { "text": "Mechwarriors", "value": "MECHWARRIORS" }, + { "text": "Memorial", "value": "MEMORIAL" }, + { "text": "Argo Upgrade", "value": "ARGOUPGRADE" }, + { "text": "Mechlab", "value": "MECHLAB" }, + { "text": "Breakdown", "value": "BREAKDOWN" }, + { "text": "Commander", "value": "COMMANDER" }, + { "text": "Hologram", "value": "HOLOGRAM" }, + { "text": "Heraldry", "value": "HERALDRY" } + ] + } + ] +} \ No newline at end of file diff --git a/operations/sideload_conversation.json b/operations/sideload_conversation.json new file mode 100644 index 0000000..3f1ba4c --- /dev/null +++ b/operations/sideload_conversation.json @@ -0,0 +1,31 @@ +{ + "key": "Sideload Conversation", + "label": "Sideload conversation", + "view": ["label", "inputs"], + "scope": "action", + "category": "primary", + "tooltip": "This will sideload a conversation into an already running conversation. Useful for having a top level conversation that loads others based on high level conditions. Important: Its recommeneded you set this action on Responses. If you set on a Prompt node then the following Response might not evaluate its condition but it will work for sideloading.", + "inputs": [ + { + "label": "Conversation Id", + "types": ["string"], + "viewLabel": "for conversation id {value}" + }, + { + "label": "Entry Node Id", + "types": ["string"], + "tooltip": "The Prompt / Response node to sideload directly into the conversation on. If left blank then it will enter the conversation like normal (and evalute all conditions on root nodes).", + "viewLabel": "and enter at node id {value}" + }, + { + "label": "Resume host after sideload finished", + "types": ["int"], + "tooltip": "This setting can allow the conversation to resume from this point after the sideloaded conversation has finished.", + "values": [ + { "viewlabel": "", "text": "False", "value": 0 }, + { "viewlabel": "and resume the host conversation on finish", "text": "True", "value": 1 } + ], + "defaultValue": 1 + } + ] +} diff --git a/operations/start_conversation.json b/operations/start_conversation.json index 1398c4e..c4bb089 100644 --- a/operations/start_conversation.json +++ b/operations/start_conversation.json @@ -35,7 +35,7 @@ "value": 1 } ], - "defaultValue": 1 + "defaultValue": 0 } ] } diff --git a/src/Core/Actions.cs b/src/Core/Actions.cs index 5c678fc..a37e29a 100644 --- a/src/Core/Actions.cs +++ b/src/Core/Actions.cs @@ -14,12 +14,24 @@ using ExtendedConversations; using ExtendedConversations.Utils; +using ExtendedConversations.State; namespace ExtendedConversations.Core { public class Actions { + public static bool IsNodeAction { get; set; } = false; + public static bool IsLinkAction { get; set; } = false; // Response or Root + + // TODO: Move all this into a state class public static bool MovedKameraInLeopardCommandCenter = false; public static bool ForceNextIsInFlashpointCheckFalse = false; public static Conversation ActiveConversation = null; + public static string HardLockTarget = null; + + // Sideload Conversation state + public static bool ReplaceLinkOnResponseIfNeeded { get; set; } = false; + public static bool SideLoadCaptureNextResponseIndex { get; set; } = false; + public static Dictionary SideLoadCachedState = new Dictionary(); + public static Dictionary SideloadConversationMap = new Dictionary(); // public static object TimeSkip(TsEnvironment env, object[] inputs) { int daysToSkip = env.ToInt(inputs[0]); @@ -141,10 +153,125 @@ public static object StartConversation(TsEnvironment env, object[] inputs) { static IEnumerator WaitThenQueueConversation(SimGameState simulation, Conversation conversation, string groupHeader, string groupSubHeader) { yield return new WaitForSeconds(1); - SimGameInterruptManager interruptManager = (SimGameInterruptManager)ReflectionHelper.GetPrivateField(simulation, "interruptQueue"); + SimGameInterruptManager interruptManager = simulation.interruptQueue; interruptManager.QueueConversation(conversation, groupHeader, groupSubHeader, null, true); } + public static object SideloadConversation(TsEnvironment env, object[] inputs) { + string conversationId = env.ToString(inputs[0]); + string nodeEntryId = env.ToString(inputs[1]); + bool resumeHostOnFinish = env.ToBool(inputs[2]); + Main.Logger.Log($"[SideloadConversation] Sideload conversation id: " + conversationId + " with nodeEntryId: " + nodeEntryId + " with resumeHostOnFinish: " + resumeHostOnFinish); + if (IsNodeAction) Main.Logger.Log($"[SideloadConversation] Sideload conversation is a node action"); + if (IsLinkAction) Main.Logger.Log($"[SideloadConversation] Sideload conversation is a link action"); + ReplaceLinkOnResponseIfNeeded = true; + + Conversation conversation = null; + SimGameState simGame = UnityGameInstance.Instance.Game.Simulation; + SimGameConversationManager conversationManager = simGame.ConversationManager; + Conversation currentConversation = conversationManager.thisConvoDef; + + try { + conversation = simGame.DataManager.SimGameConversations.Get(conversationId); + } catch (KeyNotFoundException) { + Main.Logger.Log($"[SideloadConversation] Conversation with id '{conversationId}' not found. Check the conversation id is correct or/and if the conversation has loaded correctly."); + } + + if (conversation == null) { + Main.Logger.Log($"[SideloadConversation] Conversation is null for id '{conversationId}'"); + } else { + if (resumeHostOnFinish) { + SideloadConversationState cachedState = new SideloadConversationState(); + cachedState.convoDef = currentConversation; + cachedState.currentLink = conversationManager.currentLink; + cachedState.currentNode = conversationManager.currentNode; + cachedState.state = conversationManager.thisState; + cachedState.linkToAutoFollow = conversationManager.linkToAutoFollow; + cachedState.onlyOnceLinks = conversationManager.onlyOnceLinks; + + // Handle action being on a Response + if (IsLinkAction) { + Main.Logger.Log($"[SideloadConversation] Is link action - use hydrate node instead"); + cachedState.useNodeOnHydrate = true; + + bool isNodeInAutofollowMode = false; + bool forceEnd = conversationManager.EvaluateNode(conversationManager.currentNode, out isNodeInAutofollowMode); + Main.Logger.Log("[SideloadConversation] Current node is in autofollow response mode? " + isNodeInAutofollowMode); + + if (isNodeInAutofollowMode) { + // Handle action being on an 'Autofollow Response' + for (int i = 0; i < conversationManager.currentNode.branches.Count; i++) { + ConversationLink conversationLink = conversationManager.currentNode.branches[i]; + if (conversationLink.responseText == "") { + cachedState.nextNodeIndex = conversationLink.nextNodeIndex; + } + } + } else { + // Handle action being on a 'Text Response' + cachedState.nextNodeIndex = conversationManager.currentLink.nextNodeIndex; + } + } + + cachedState.previousNodes = new List(); + foreach (ConversationNode prevNode in conversationManager.previousNodes) { + cachedState.previousNodes.Add(prevNode); + } + + Actions.SideLoadCachedState.Add(currentConversation.idRef.id, cachedState); + Actions.SideloadConversationMap.Add(conversation.idRef.id, currentConversation.idRef.id); + + SideLoadCaptureNextResponseIndex = true; + } + + conversationManager.thisConvoDef = conversation; + conversationManager.currentNode = null; + conversationManager.currentLink = null; + conversationManager.previousNodes.Clear(); + + ConversationNode conversationNode = new ConversationNode(); + conversationNode.index = -1; + for (int i = 0; i < conversation.roots.Count; i++) { + conversationNode.branches.Add(conversation.roots[i]); + } + conversationManager.currentNode = conversationNode; + + bool autoFollow = false; + bool passedConditions = conversationManager.EvaluateNode(conversationNode, out autoFollow); + if (autoFollow && passedConditions) { + conversationManager.EndConversation(); + } + + // Find the entry node if provided + if (nodeEntryId == "") { + conversationManager.thisState = BattleTech.SimGameConversationManager.ConversationState.NODE; + } else { + int entryNodeIndex = conversation.nodes.FindIndex((node => node.idRef.id == nodeEntryId)); + + if (entryNodeIndex != -1) { + conversationManager.thisState = BattleTech.SimGameConversationManager.ConversationState.RESPONSE; + + ConversationLink conversationLink = new ConversationLink(); + conversationLink.onlyOnce = false; + conversationLink.idRef = new IDRef(); + conversationLink.idRef.id = Guid.NewGuid().ToString(); + conversationLink.nextNodeIndex = entryNodeIndex; + + conversationManager.currentLink = conversationLink; + } else { + ConversationLink rootLinkToFollow = conversation.GetRootToFollow(); + if (rootLinkToFollow == null) rootLinkToFollow = conversation.roots[0]; + conversationManager.currentLink = rootLinkToFollow; + conversationManager.linkToAutoFollow = 0; + } + } + } + + IsNodeAction = false; + IsLinkAction = false; + + return null; + } + public static object AddContract(TsEnvironment env, object[] inputs) { string contractId = env.ToString(inputs[0]); string target = env.ToString(inputs[1]); @@ -199,5 +326,16 @@ public static object AddFlashpoint(TsEnvironment env, object[] inputs) { return null; } + + public static object SetCameraHardLock(TsEnvironment env, object[] inputs) { + string key = env.ToString(inputs[0]); + + Main.Logger.Log($"[SetCameraHardLock] Received key '{key}'"); + HardLockTarget = key; + + UnityGameInstance.BattleTechGame.Simulation.ConversationManager.SetCameraLockTarget(key); + + return null; + } } } \ No newline at end of file diff --git a/src/Core/ConversationUpgrades.cs b/src/Core/ConversationUpgrades.cs index 1816879..6761cee 100644 --- a/src/Core/ConversationUpgrades.cs +++ b/src/Core/ConversationUpgrades.cs @@ -98,6 +98,14 @@ public static void Declare(TsEnvironment env) { tsOp.DeclareInput("conversationId", stringType); tsOp.DeclareInput("groupHeader", stringType); tsOp.DeclareInput("groupSubHeader", stringType); + tsOp.DeclareInput("forceNonFPConferenceRoom", intType); + + // 'Sideload Conversation' action + Main.Logger.Log("Declaring 'Sideload Conversation' action"); + tsOp = env.DeclareOp("EffectFunctions", "Sideload Conversation", voidType, new TsOp.EvalDelegate(Actions.SideloadConversation)); + tsOp.DeclareInput("conversationId", stringType); + tsOp.DeclareInput("nodeEntryId", stringType); + tsOp.DeclareInput("resumeHostOnFinish", intType); // 'Add Contract' action Main.Logger.Log("Declaring 'Add Contract' action"); @@ -113,6 +121,11 @@ public static void Declare(TsEnvironment env) { tsOp.DeclareInput("flashpointId", stringType); tsOp.DeclareInput("systemId", stringType); + // 'Set BattleTech Camera Hard Lock' action + Main.Logger.Log("Declaring 'Set BattleTech Camera Hard Lock' action"); + tsOp = env.DeclareOp("EffectFunctions", "Set BattleTech Camera Hard Lock", voidType, new TsOp.EvalDelegate(Actions.SetCameraHardLock)); + tsOp.DeclareInput("key", stringType); + /* * VALUE GETTERS */ diff --git a/src/ExtendedConversations.csproj b/src/ExtendedConversations.csproj index 332c1d6..e27a3de 100644 --- a/src/ExtendedConversations.csproj +++ b/src/ExtendedConversations.csproj @@ -1,13 +1,24 @@ - 0.4.5 + 0.5.0 Library net471 + + + Unsafe + + + + + + + + - D:\Program Files (x86)\Steam\steamapps\common\BATTLETECH\Mods\ModTek\0Harmony.dll + D:\Program Files (x86)\Steam\steamapps\common\BATTLETECH\BattleTech_Data\Managed\0Harmony.dll D:\Program Files (x86)\Steam\steamapps\common\BATTLETECH\BattleTech_Data\Managed\UnityEngine.dll diff --git a/src/Patches/Actions/General/SimGameConversationManagerDoLinkActionsPatch.cs b/src/Patches/Actions/General/SimGameConversationManagerDoLinkActionsPatch.cs new file mode 100644 index 0000000..8d792c6 --- /dev/null +++ b/src/Patches/Actions/General/SimGameConversationManagerDoLinkActionsPatch.cs @@ -0,0 +1,17 @@ +using Harmony; + +using BattleTech; + +using isogame; + +using ExtendedConversations.Core; + +namespace ExtendedConversations { + [HarmonyPatch(typeof(SimGameConversationManager), "DoLinkActions")] + public class SimGameConversationManagerDoLinkActionsPatch { + static void Prefix(SimGameConversationManager __instance) { + Actions.IsLinkAction = true; + Actions.IsNodeAction = false; + } + } +} \ No newline at end of file diff --git a/src/Patches/Actions/General/SimGameConversationManagerDoNodeActionsPatch.cs b/src/Patches/Actions/General/SimGameConversationManagerDoNodeActionsPatch.cs new file mode 100644 index 0000000..a8c631b --- /dev/null +++ b/src/Patches/Actions/General/SimGameConversationManagerDoNodeActionsPatch.cs @@ -0,0 +1,15 @@ +using Harmony; + +using BattleTech; + +using ExtendedConversations.Core; + +namespace ExtendedConversations { + [HarmonyPatch(typeof(SimGameConversationManager), "DoNodeActions")] + public class SimGameConversationManagerDoNodeActionsPatch { + static void Prefix(SimGameConversationManager __instance) { + Actions.IsLinkAction = false; + Actions.IsNodeAction = true; + } + } +} \ No newline at end of file diff --git a/src/Patches/Actions/General/SimGameConversationManagerEndConversationPatch.cs b/src/Patches/Actions/General/SimGameConversationManagerEndConversationPatch.cs new file mode 100644 index 0000000..125706d --- /dev/null +++ b/src/Patches/Actions/General/SimGameConversationManagerEndConversationPatch.cs @@ -0,0 +1,77 @@ +using Harmony; + +using BattleTech; +using isogame; + +using ExtendedConversations.Core; +using ExtendedConversations.State; + +namespace ExtendedConversations { + [HarmonyPatch(typeof(SimGameConversationManager), "EndConversation")] + public class SimGameConversationManagerEndConversationPatch { + static bool Prefix(SimGameConversationManager __instance) { + if (ProcessSideloadConversationPatch(__instance)) return false; + ProcessForceNonFPConferenceRoomPatch(__instance); + + return true; + } + + private static void ProcessForceNonFPConferenceRoomPatch(SimGameConversationManager simGameConversationManager) { + Conversation conversation = simGameConversationManager.thisConvoDef; + + if (Actions.ActiveConversation == conversation) { + Actions.ForceNextIsInFlashpointCheckFalse = false; + Actions.ActiveConversation = null; + } + + Actions.HardLockTarget = null; + } + + private static bool ProcessSideloadConversationPatch(SimGameConversationManager simGameConversationManager) { + Conversation conversation = simGameConversationManager.thisConvoDef; + string conversationId = conversation.idRef.id; + + if (Actions.SideloadConversationMap.ContainsKey(conversationId)) { + string previousConversationId = Actions.SideloadConversationMap[conversationId]; + SideloadConversationState cachedState = Actions.SideLoadCachedState[previousConversationId]; + + simGameConversationManager.thisConvoDef = cachedState.convoDef; + simGameConversationManager.currentLink = cachedState.currentLink; + simGameConversationManager.currentNode = cachedState.currentNode; + simGameConversationManager.thisState = cachedState.state; + simGameConversationManager.linkToAutoFollow = cachedState.linkToAutoFollow; + simGameConversationManager.onlyOnceLinks = cachedState.onlyOnceLinks; + simGameConversationManager.previousNodes.Clear(); + + foreach (ConversationNode prevNode in cachedState.previousNodes) { + simGameConversationManager.previousNodes.Add(prevNode); + } + + Actions.SideLoadCachedState.Remove(previousConversationId); + Actions.SideloadConversationMap.Remove(conversationId); + + if (cachedState.useNodeOnHydrate) { + Main.Logger.Log("[ProcessSideloadConversationPatch] useNodeOnHydrate so attempting to use node instead"); + Main.Logger.Log("[SideloadConversation] cachedState.convoDef.nodes count" + cachedState.convoDef.nodes.Count); + Main.Logger.Log("[SideloadConversation] Using nextNodeIndex " + cachedState.nextNodeIndex); + if (cachedState.nextNodeIndex > -1) { + simGameConversationManager.currentNode = cachedState.convoDef.nodes[cachedState.nextNodeIndex]; + simGameConversationManager.ShowNodeText(simGameConversationManager.currentNode); + } else { + return false; + } + } else { + if (simGameConversationManager.currentLink.responseText == "") { + simGameConversationManager.Continue(true); + } else { + simGameConversationManager.SelectResponse(cachedState.ResponseIndexClicked); + } + } + + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/src/Patches/Actions/General/SimGameConversationManagerResolveLinkPatch.cs b/src/Patches/Actions/General/SimGameConversationManagerResolveLinkPatch.cs new file mode 100644 index 0000000..cd173c6 --- /dev/null +++ b/src/Patches/Actions/General/SimGameConversationManagerResolveLinkPatch.cs @@ -0,0 +1,27 @@ +using Harmony; + +using BattleTech; + +using isogame; + +using ExtendedConversations.Core; + +namespace ExtendedConversations { + [HarmonyPatch(typeof(SimGameConversationManager), "ResolveLink")] + public class SimGameConversationManagerResolveLinkPatch { + static void Prefix(SimGameConversationManager __instance, ref ConversationLink link) { + // Pre-run DoLinkActions(link) to get ahead of the link issue + __instance.DoLinkActions(link); + + // If the link actions had a 'sideload conversation' action then replace the link going into ResolveLink + if (Actions.ReplaceLinkOnResponseIfNeeded) { + link = __instance.currentLink; + Actions.ReplaceLinkOnResponseIfNeeded = false; + } + } + + static void Postfix(SimGameConversationManager __instance, ref ConversationLink link) { + Actions.ReplaceLinkOnResponseIfNeeded = false; + } + } +} \ No newline at end of file diff --git a/src/Patches/Actions/SetCameraHardLock/SimGameCameraControllerTransitionCameraPatch.cs b/src/Patches/Actions/SetCameraHardLock/SimGameCameraControllerTransitionCameraPatch.cs new file mode 100644 index 0000000..ec40a17 --- /dev/null +++ b/src/Patches/Actions/SetCameraHardLock/SimGameCameraControllerTransitionCameraPatch.cs @@ -0,0 +1,21 @@ +using Harmony; + +using BattleTech; + +using System; + +using ExtendedConversations.Core; + +namespace ExtendedConversations { + [HarmonyPatch(typeof(SimGameCameraController), "TransitionCamera")] + [HarmonyPatch(new Type[] { typeof(SimGameState.SimGameCharacterType), typeof(bool) })] + public class SimGameCameraControllerTransitionCameraPatch { + static bool Prefix(SimGameCameraController __instance, SimGameState.SimGameCharacterType character) { + if (Actions.HardLockTarget != null && Actions.HardLockTarget != character.ToString()) { + return false; + } + + return true; + } + } +} \ No newline at end of file diff --git a/src/Patches/Actions/SideloadConversation/SimGameConversationManagerSelectResponsePatch.cs b/src/Patches/Actions/SideloadConversation/SimGameConversationManagerSelectResponsePatch.cs new file mode 100644 index 0000000..f87b848 --- /dev/null +++ b/src/Patches/Actions/SideloadConversation/SimGameConversationManagerSelectResponsePatch.cs @@ -0,0 +1,24 @@ +using Harmony; + +using BattleTech; + +using ExtendedConversations.Core; +using ExtendedConversations.State; + +namespace ExtendedConversations { + [HarmonyPatch(typeof(SimGameConversationManager), "SelectResponse")] + public class SimGameConversationManagerSelectResponsePatch { + static void Prefix(SimGameConversationManager __instance, int num) { + if (Actions.SideLoadCaptureNextResponseIndex) { + Actions.SideLoadCaptureNextResponseIndex = false; + string currentConversationId = __instance.thisConvoDef.idRef.id; + + if (Actions.SideloadConversationMap.ContainsKey(currentConversationId)) { + string previousConversationId = Actions.SideloadConversationMap[currentConversationId]; + SideloadConversationState cachedState = Actions.SideLoadCachedState[previousConversationId]; + cachedState.ResponseIndexClicked = num; + } + } + } + } +} \ No newline at end of file diff --git a/src/Patches/ForceNonFPConferenceRoom/SimGameConversationManagerEndConversationPatch.cs b/src/Patches/ForceNonFPConferenceRoom/SimGameConversationManagerEndConversationPatch.cs deleted file mode 100644 index bc6f035..0000000 --- a/src/Patches/ForceNonFPConferenceRoom/SimGameConversationManagerEndConversationPatch.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Harmony; - -using BattleTech; -using isogame; - -using ExtendedConversations.Core; - -namespace ExtendedConversations { - [HarmonyPatch(typeof(SimGameConversationManager), "EndConversation")] - public class SimGameConversationManagerEndConversationPatch { - static void Prefix(SimGameConversationManager __instance) { - Conversation conversation = (Conversation)AccessTools.Field(typeof(SimGameConversationManager), "thisConvoDef").GetValue(__instance); - - if (Actions.ActiveConversation == conversation) { - Actions.ForceNextIsInFlashpointCheckFalse = false; - Actions.ActiveConversation = null; - } - } - } -} \ No newline at end of file diff --git a/src/State/SideloadConversationState.cs b/src/State/SideloadConversationState.cs new file mode 100644 index 0000000..ab7f9a7 --- /dev/null +++ b/src/State/SideloadConversationState.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; + +using BattleTech; + +using isogame; + + +namespace ExtendedConversations.State { + public class SideloadConversationState { + public Conversation convoDef { get; set; } + public bool useNodeOnHydrate { get; set; } + public int nextNodeIndex { get; set; } + public ConversationNode currentNode { get; set; } + public ConversationLink currentLink { get; set; } + public SimGameConversationManager.ConversationState state { get; set; } + public List onlyOnceLinks { get; set; } + public int linkToAutoFollow { get; set; } + public List previousNodes { get; set; } + public int ResponseIndexClicked { get; set; } + } +} \ No newline at end of file diff --git a/src/Util/ConversationExtensions.cs b/src/Util/ConversationExtensions.cs new file mode 100644 index 0000000..25b0128 --- /dev/null +++ b/src/Util/ConversationExtensions.cs @@ -0,0 +1,20 @@ +using BattleTech; + +using isogame; + +public static class ConversationExtensions { + public static ConversationLink GetRootToFollow(this Conversation conversation) { + SimGameConversationManager conversationManager = UnityGameInstance.Instance.Game.Simulation.ConversationManager; + + for (int i = 0; i < conversation.roots.Count; i++) { + ConversationLink conversationLink = conversation.roots[i]; + if (conversationManager.EvaluateLink(conversationLink)) { + if (conversationLink.responseText == "") { + return conversationLink; + } + } + } + + return null; + } +} \ No newline at end of file diff --git a/tests/sideload-conversation/ec-sideload-conversation-test-sl-convo1.9c61ca1702e45794ec03824f.convo.bytes b/tests/sideload-conversation/ec-sideload-conversation-test-sl-convo1.9c61ca1702e45794ec03824f.convo.bytes new file mode 100644 index 0000000..9d4f434 Binary files /dev/null and b/tests/sideload-conversation/ec-sideload-conversation-test-sl-convo1.9c61ca1702e45794ec03824f.convo.bytes differ diff --git a/tests/sideload-conversation/ec-sideload-conversation-test-sl-convo2.9c2cb601a7420cb4a1d9977f.convo.bytes b/tests/sideload-conversation/ec-sideload-conversation-test-sl-convo2.9c2cb601a7420cb4a1d9977f.convo.bytes new file mode 100644 index 0000000..7b53fb6 Binary files /dev/null and b/tests/sideload-conversation/ec-sideload-conversation-test-sl-convo2.9c2cb601a7420cb4a1d9977f.convo.bytes differ diff --git a/tests/sideload-conversation/ec-sideload-conversation-test.9cd4e6f32d7611cb3f5a73ba.bytes b/tests/sideload-conversation/ec-sideload-conversation-test.9cd4e6f32d7611cb3f5a73ba.bytes new file mode 100644 index 0000000..87c61d0 Binary files /dev/null and b/tests/sideload-conversation/ec-sideload-conversation-test.9cd4e6f32d7611cb3f5a73ba.bytes differ