示例#1
0
        protected bool BuildChoices(BaseDialogueObject fromObject, List <DialogueFragment> fragments)
        {
            IList <GraphPin> pins;

            if (fromObject is Dialogue)
            {
                pins = fromObject.Inputs;
            }
            else if (fromObject is DialogueCondition)
            {
                DialogueCondition condition = (DialogueCondition)fromObject;
                if (condition.Script == null)
                {
                    GameDebugger.Log(LogLevel.Warning, "Condition '0x{0:X16}' has no script", condition.Id);
                    return(true);
                }
                dynamic result = condition.Script.Run(this);
                if (!(result is Boolean))
                {
                    GameDebugger.Log(LogLevel.Warning, "Condition '0x{0:X16}' script exits with a non boolean result ({1})", condition.Id, result.GetType().Name);
                    return(true);                    // end the dialogue due to error
                }
                pins = new List <GraphPin>();
                pins.Add(condition.Outputs[result ? 0 : 1]);
            }
            else
            {
                if (fromObject is DialogueFragment)
                {
                    DialogueFragment fragment = (DialogueFragment)fromObject;
                    if (!string.IsNullOrWhiteSpace(fragment.MenuText))
                    {
                        fragments.Add(fragment);
                        return(false);
                    }

                    if (OnActorTalk != null)
                    {
                        OnActorTalk.Invoke(new ActorTalkEventArgs(fragment));
                    }
                }
                pins = fromObject.Outputs;
            }

            if (fromObject is DialogueInstruction)
            {
                DialogueInstruction instruction = (DialogueInstruction)fromObject;
                if (instruction.Script != null)
                {
                    instruction.Script.Run(this);
                }
            }

            if (fromObject is DialogueJump)
            {
                DialogueJump jump = (DialogueJump)fromObject;
                if (jump.TargetPin != null)
                {
                    if (BuildChoices(jump.TargetPin, fragments))
                    {
                        return(true);
                    }
                }
                else if (jump.Target != null)
                {
                    if (BuildChoices(jump.Target, fragments))
                    {
                        return(true);
                    }
                }
            }

            foreach (GraphPin gpin in pins)
            {
                if (BuildChoices(gpin, fragments))
                {
                    return(true);
                }
            }
            return(false);
        }
示例#2
0
        public static bool ImportArticyDialogues(Project project, string dialogueContainerExternalId)
        {
            ArticyFlowObject dialogueContainer;

            try {
                dialogueContainer = project.GetFlowObject(dialogueContainerExternalId);
            }
            catch {
                throw new UserFriendlyException(
                          String.Format("Could not find dialogue container '{0}' in the project.", dialogueContainerExternalId),
                          "One of data files does not contain required information."
                          );
            }

            IList <GraphNode> dialogues = dialogueContainer.Children;

            GameDebugger.Log(LogLevel.Debug, "{0} dialogues found:", dialogues.Count);

            ArticyDialogue articyDialogue;
            Dialogue       dialogue;
            Dictionary <ulong, DialoguePin> pinIndex = new Dictionary <ulong, DialoguePin>();
            List <Jump>  articyJumps = new List <Jump>();
            DialogueJump jump;
            bool         badScripts = false;

            // copy dialogues
            foreach (GraphNode node in dialogueContainer.Children)
            {
                if (!(node is ArticyDialogue))
                {
                    continue;
                }
                articyDialogue = (ArticyDialogue)node;
                dialogue       = new Dialogue(articyDialogue.Id, articyDialogue.ExternalId);

                GameDebugger.Log(LogLevel.Debug, "Importing dialogue '{0}'", dialogue.Key);
                GameDebugger.Log(LogLevel.Debug, "Dialogue has {0} inputs and {1} outputs", articyDialogue.Inputs.Count, articyDialogue.Outputs.Count);

                badScripts |= ImportArticyPins(articyDialogue, dialogue, false, false, pinIndex);

                Add(dialogue);

                // copy dialogue fragments
                foreach (GraphNode childNode in node.Children)
                {
                    if (childNode is ArticyFlowFragment)
                    {
                        throw new UserFriendlyException(
                                  String.Format("FlowFragment '0x{0:X16}' is not supposed to be a part of a dialogue", ((ArticyFlowFragment)childNode).Id),
                                  "One of data files is either corupt or has a version that is not supported by the game engine."
                                  );
                    }

                    if (childNode is ArticyDialogueFragment)
                    {
                        ArticyDialogueFragment articyFragment = (ArticyDialogueFragment)childNode;
                        DialogueFragment       fragment       = new DialogueFragment(articyFragment.Id, articyFragment.ExternalId);
                        fragment.ActorId  = (articyFragment.Speaker == null) ? 0UL : articyFragment.Speaker.Id;
                        fragment.MenuText = articyFragment.MenuText;
                        fragment.Text     = articyFragment.Text;
                        fragment.Extra    = articyFragment.StageDirections;
                        badScripts       |= ImportArticyPins(articyFragment, fragment, true, true, pinIndex);
                        GameDebugger.Log(LogLevel.Debug, "Adding fragment '0x{0:X16}' to the dialogue", fragment.Id);
                        dialogue.AddChild(fragment);
                        Add(fragment);
                    }

                    if (childNode is ArticyCondition)
                    {
                        ArticyCondition   articyCondition = (ArticyCondition)childNode;
                        DialogueCondition condition       = new DialogueCondition(articyCondition.Id, articyCondition.ExternalId);
                        if (string.IsNullOrWhiteSpace(articyCondition.Script))
                        {
                            badScripts = true;
                            GameDebugger.Log(LogLevel.Error, "Condition '0x{0:X16}' has no script", condition.Id);
                        }
                        else
                        {
                            if ((condition.Script = CompileScript(articyCondition.Script, Dialogues.ConditionScriptEnvironment, "condition", condition.Id)) == null)
                            {
                                badScripts = true;
                            }
                        }
                        badScripts |= ImportArticyPins(articyCondition, condition, true, true, pinIndex);
                        GameDebugger.Log(LogLevel.Debug, "Adding condition '0x{0:X16}' to the dialogue", condition.Id);
                        dialogue.AddChild(condition);
                        Add(condition);
                    }

                    if (childNode is ArticyInstruction)
                    {
                        ArticyInstruction   articyInstruction = (ArticyInstruction)childNode;
                        DialogueInstruction instruction       = new DialogueInstruction(articyInstruction.Id, articyInstruction.ExternalId);
                        if (string.IsNullOrWhiteSpace(articyInstruction.Script))
                        {
                            GameDebugger.Log(LogLevel.Notice, "Instruction '0x{0:X16}' has no script", instruction.Id);
                        }
                        else
                        {
                            if ((instruction.Script = CompileScript(articyInstruction.Script, Dialogues.ConditionScriptEnvironment, "instruction", instruction.Id)) == null)
                            {
                                badScripts = true;
                            }
                        }
                        badScripts |= ImportArticyPins(articyInstruction, instruction, true, true, pinIndex);
                        GameDebugger.Log(LogLevel.Debug, "Adding instruction '0x{0:X16}' to the dialogue", instruction.Id);
                        dialogue.AddChild(instruction);
                        Add(instruction);
                    }

                    if (childNode is ArticyHub)
                    {
                        ArticyHub   articyHub = (ArticyHub)childNode;
                        DialogueHub hub       = new DialogueHub(articyHub.Id, articyHub.ExternalId);
                        badScripts |= ImportArticyPins(articyHub, hub, true, true, pinIndex);
                        GameDebugger.Log(LogLevel.Debug, "Adding hub '0x{0:X16}' to the dialogue", hub.Id);
                        dialogue.AddChild(hub);
                        Add(hub);
                    }

                    if (childNode is Jump)
                    {
                        Jump articyJump = (Jump)childNode;
                        jump        = new DialogueJump(articyJump.Id, articyJump.ExternalId);
                        badScripts |= ImportArticyPins(articyJump, jump, true, true, pinIndex);
                        GameDebugger.Log(LogLevel.Debug, "Adding jump '0x{0:X16}' to the dialogue", jump.Id);
                        m_Objects.Add(jump.Id, jump);
                        dialogue.AddChild(jump);
                        Add(jump);
                        articyJumps.Add(articyJump);
                    }
                }
            }

            // jumps need postprocessing, because we must make sure all dialogue system nodes are already added
            BaseDialogueObject obj;
            DialoguePin        pin;

            foreach (Jump articyJump in articyJumps)
            {
                jump = (DialogueJump)m_Objects[articyJump.Id];

                GameDebugger.Log(LogLevel.Debug, "Linking jump '0x{0:X16}'", jump.Id);

                if (articyJump.Target != null)
                {
                    if (!m_Objects.TryGetValue(articyJump.Target.Id, out obj))
                    {
                        throw new UserFriendlyException(
                                  String.Format("Jump '0x{0:X16}' references an object outside the dialogue container", jump.Id),
                                  "One of data files is either corupt or has a version that is not supported by the game engine."
                                  );
                    }
                    jump.Target = obj;
                    GameDebugger.Log(LogLevel.Debug, "Linked target to {0} '0x{1:X16}'", obj.GetType().Name, obj.Id);
                }

                if (articyJump.TargetPin != null)
                {
                    if (articyJump.TargetPin.Node == dialogueContainer)
                    {
                        throw new UserFriendlyException(
                                  String.Format("Jump '0x{0:X16}' references a pin of the dialogue container itself", jump.Id),
                                  "One of data files is either corupt or has a version that is not supported by the game engine."
                                  );
                    }
                    if (!pinIndex.TryGetValue(articyJump.TargetPin.Id, out pin))
                    {
                        throw new UserFriendlyException(
                                  String.Format("Jump '0x{0:X16}' references a pin outside the dialogue container", jump.Id),
                                  "One of data files is either corupt or has a version that is not supported by the game engine."
                                  );
                    }
                    jump.TargetPin = pin;
                    GameDebugger.Log(LogLevel.Debug, "Linked target pin to '0x{0:X16}'", articyJump.TargetPin.Id);
                }
            }

            // recreate connections
            DialoguePin srcPin, dstPin;

            foreach (ArticyFlowConnection articyConnection in project.FlowConnections)
            {
                if (articyConnection.Source.Node is ArticyFlowFragment ||
                    articyConnection.Target.Node is ArticyFlowFragment ||
                    (articyConnection.Source.Node is ArticyDialogue && articyConnection.Target.Node is ArticyDialogue) ||
                    !pinIndex.TryGetValue(((FlowObjectPin)articyConnection.Source).Id, out srcPin) ||
                    !pinIndex.TryGetValue(((FlowObjectPin)articyConnection.Target).Id, out dstPin)
                    )
                {
                    continue;
                }

                GraphConnection newConnection = new GraphConnection();
                newConnection.Source = srcPin;
                newConnection.Target = dstPin;

                GameDebugger.Log(LogLevel.Debug, "Connected '0x{0:X16}' to '0x{1:X16}'", ((BaseDialogueObject)newConnection.Source.Node).Id, ((BaseDialogueObject)newConnection.Target.Node).Id);
            }

            return(badScripts);
        }