static void Main(string[] args) { //if (args.Length == 0) // args = new string[] // { // @"c:\Games\Pillars of Eternity\PillarsOfEternity_Data\data\conversations\companions\companion_cv_durance_v2.conversation" // }; try { if (args.Length > 0) { ResourceLocator.Initialize(args[0]); } else { ResourceLocator.Initialize(Settings.Instance.GamePath); } } catch (Exception e) { Console.Error.WriteLine("Error: " + e); Console.ReadKey(true); return; } // ValidateAllConversations(); if (args.Length == 0 || !args[0].EndsWith(".conversation")) { Console.WriteLine("Usage: PoEDlgExplorer.exe <conversation path>"); Console.ReadKey(true); return; } Console.WriteLine("[HOW-TO]"); Console.WriteLine(); Console.WriteLine("0..9: select a dialogue line"); Console.WriteLine("ENTER: commit when there are 10+ options"); Console.WriteLine("BACKSPACE: rewind"); Console.WriteLine("SPACE: toggle audio"); Console.WriteLine("ESC: quit"); Console.WriteLine("\n"); Conversation conversation; try { conversation = LoadConversationByPath(new FileInfo(args[0]), Settings.Instance.Localization); } catch (Exception e) { Console.Error.WriteLine("Error: " + e); Console.ReadKey(true); return; } bool audioEnabled = Settings.Instance.PlayAudio; var linkStack = new Stack <ConversationLink>(); linkStack.Push(new ConversationLink(conversation, -1, 0)); PrintNode(linkStack.Peek(), audioEnabled); Command command; do { FlowChartNode node = conversation.FindNode(linkStack.Peek().Link.ToNodeID); FlowChartLink pickedLink; command = ReadInput(node, out pickedLink); switch (command) { case Command.PickLine: AudioServer.Stop(); Console.Clear(); linkStack.Push(new ConversationLink(conversation, pickedLink)); FlowChartNode targetNode = conversation.FindNode(pickedLink.ToNodeID); if (targetNode is PlayerResponseNode && targetNode.Links.Count == 1) { // skip player response nodes linkStack.Pop(); linkStack.Push(new ConversationLink(conversation, targetNode.Links[0])); } PrintNode(linkStack.Peek(), audioEnabled); break; case Command.Rewind: if (linkStack.Count > 1) { AudioServer.Stop(); Console.Clear(); linkStack.Pop(); conversation = linkStack.Peek().Conversation; PrintNode(linkStack.Peek(), false); } break; case Command.Confirm: var triggerNode = node as TriggerConversationNode; if (triggerNode != null) { AudioServer.Stop(); Console.Clear(); string tag = Path.GetFileNameWithoutExtension(triggerNode.ConversationFilename); if (tag != conversation.Tag) { conversation = LoadConversation(tag, Settings.Instance.Localization); } int startNodeID = triggerNode.StartNodeID; if (!conversation.Nodes.ContainsKey(startNodeID)) { Console.Error.WriteLine("Invalid start node!"); startNodeID = 0; } linkStack.Push(new ConversationLink(conversation, -1, startNodeID)); PrintNode(linkStack.Peek(), audioEnabled); } break; case Command.QuitProgram: break; case Command.ToggleAudio: if (audioEnabled) { audioEnabled = false; AudioServer.Stop(); } else { audioEnabled = true; FileInfo audioFile = ResourceLocator.FindVocalization(conversation.Tag, node.NodeID); if (audioFile != null) { AudioServer.Play(audioFile); } } break; default: throw new ArgumentOutOfRangeException(); } } while (command != Command.QuitProgram); AudioServer.Kill(); }
private static void PrintNode(Conversation conversation, FlowChartLink parentLink, bool playAudio) { FlowChartNode node = conversation.Nodes[parentLink.ToNodeID]; var dialogueNode = node as DialogueNode; bool keepParentBrief = (parentLink.PointsToGhost && dialogueNode != null && dialogueNode.IsQuestionNode); FlowChartNode briefNode = (keepParentBrief ? conversation.Nodes[parentLink.FromNodeID] : node); Console.WriteLine("{0}", briefNode.GetBrief()); FileInfo audioFile = ResourceLocator.FindVocalization(conversation.Tag, briefNode.NodeID); if (audioFile != null) { Console.Write("[audio] "); } StringTable.Entry text = conversation.FindText(briefNode.NodeID); if (text != null) { Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("{0}", text.Format()); Console.ForegroundColor = ConsoleColor.Gray; } Console.WriteLine("\n\n"); if (node.Links.Count + node.ChildIDs.Count == 0) { if (node is TriggerConversationNode) { Console.WriteLine("(End. Hit BACKSPACE to rewind or ENTER to load target conversation)"); } else if (node.ContainerNodeID != -1) { Console.WriteLine("(Hit BACKSPACE to rewind into container node)"); } else { Console.WriteLine("(End. Hit BACKSPACE to rewind)"); } } else { for (int i = 0; i < node.Links.Count + node.ChildIDs.Count; i++) { FlowChartNode targetNode; bool pointsToGhost = false; if (i < node.Links.Count) { FlowChartLink link = node.Links[i]; pointsToGhost = link.PointsToGhost; targetNode = conversation.FindNode(link.ToNodeID); Console.Write("({0}) {1} -> {2}", i + 1, link.GetBrief(), targetNode.GetBrief()); } else { targetNode = conversation.FindNode(node.ChildIDs[i - node.Links.Count]); Console.Write("({0}) [ child ] -> {1}", i + 1, targetNode.GetBrief()); } if (targetNode is PlayerResponseNode && targetNode.Links.Count == 1) { Console.WriteLine(" -> {0}", conversation.FindNode(targetNode.Links[0].ToNodeID).GetBrief()); } else { Console.WriteLine(); } string condition = targetNode.Conditionals.Format(); if (condition.Length > 0) { Console.WriteLine(" if : {0}", condition); } foreach (var script in targetNode.OnEnterScripts) { Console.WriteLine(" on enter : {0}", script.Format()); } foreach (var script in targetNode.OnExitScripts) { Console.WriteLine(" on exit : {0}", script.Format()); } foreach (var script in targetNode.OnUpdateScripts) { Console.WriteLine(" on update : {0}", script.Format()); } if (!pointsToGhost) { Console.ForegroundColor = ConsoleColor.White; } if (node.Links.Count + node.ChildIDs.Count == 1) { Console.WriteLine("[continue]"); } else { if (ResourceLocator.FindVocalization(conversation.Tag, targetNode.NodeID) != null) { Console.Write("[audio] "); } text = conversation.FindText(targetNode.NodeID); Console.WriteLine(text.Format()); } if (!pointsToGhost) { Console.ForegroundColor = ConsoleColor.Gray; } Console.WriteLine("\n"); } } if ((audioFile != null) && playAudio && (briefNode == node)) { AudioServer.Play(audioFile); } }