public void VisitNodeDialogue(NodeDialogue nd)
 {
     if (nd.Character == null)
     {
         _report.AddMessage(ProjectReportMessage.MessageSeverity.Error, "A dialogue node has no assigned character.", nd);
     }
     if (string.IsNullOrWhiteSpace(nd.Text))
     {
         _report.AddMessage(ProjectReportMessage.MessageSeverity.Warning, "A dialogue node has no assigned text.", nd);
     }
     if (Regex.IsMatch(nd.Text, @"[^\x00-\x7F]"))
     {
         _report.AddMessage(ProjectReportMessage.MessageSeverity.Error, "A dialogue node contains non-ASCII characters.", nd);
     }
     if (nd.Text?.Length > 300)
     {
         _report.AddMessage(ProjectReportMessage.MessageSeverity.Warning, "A dialogue node has more than 300 characters of text.", nd);
     }
     if (nd.Text?.Split('\n').Length > 3)
     {
         _report.AddMessage(ProjectReportMessage.MessageSeverity.Warning, "A dialogue node has more than 3 lines of text.", nd);
     }
 }
Beispiel #2
0
        public void InterpretScene(Scene scene, ProjectReport report)
        {
            _interpreters[0].Interpreter.Report = report;

            while (_interpreters.Count(i => i.Running) != 0)
            {
                var newStates = new List <InterpreterState>();

                foreach (var interpreter in _interpreters)
                {
                    if (!interpreter.Running)
                    {
                        continue;
                    }

                    if (scene.Nodes.Count == interpreter.Position)
                    {
                        interpreter.Running = false;
                        continue;
                    }

                    var node = scene.Nodes[interpreter.Position++];
                    node.Accept(interpreter.Interpreter);

                    if (node is NodeJump nj)
                    {
                        if (nj.Target == null)
                        {
                            continue;
                        }

                        var targetIndexJ = scene.Nodes.IndexOf(nj.Target);
                        if (targetIndexJ == -1)
                        {
                            report.AddMessage(ProjectReportMessage.MessageSeverity.Info, "Detected jump outside of current scope, aborting analysis of this branch.", nj);
                            interpreter.Running = false;
                        }
                        else if (targetIndexJ < interpreter.Position)
                        {
                            report.AddMessage(ProjectReportMessage.MessageSeverity.Info, "Detected jump backwards (potential loop), aborting analysis of this branch.", nj);
                            interpreter.Running = false;
                        }
                        interpreter.Position = targetIndexJ;
                    }
                    else if (node is NodeVariableJump nvj)
                    {
                        if (nvj.Target == null)
                        {
                            continue;
                        }

                        bool interpreterState = interpreter.Interpreter.SetVariables.Contains(nvj.Variable);
                        bool requiredState    = nvj.Value;
                        if (interpreterState != requiredState)
                        {
                            continue;
                        }

                        var targetIndexVJ = scene.Nodes.IndexOf(nvj.Target);
                        if (targetIndexVJ == -1)
                        {
                            report.AddMessage(ProjectReportMessage.MessageSeverity.Info, "Detected jump outside of current scope, aborting analysis of this branch.", nvj);
                            interpreter.Running = false;
                        }
                        else if (targetIndexVJ < interpreter.Position)
                        {
                            report.AddMessage(ProjectReportMessage.MessageSeverity.Info, "Detected jump backwards (potential loop), aborting analysis of this branch.", nvj);
                            interpreter.Running = false;
                        }

                        interpreter.Position = targetIndexVJ;
                    }
                    else if (node is NodeCall nc)
                    {
                        var targetIndexC = scene.Nodes.IndexOf(nc.Target);
                        if (targetIndexC != -1)
                        {
                            report.AddMessage(ProjectReportMessage.MessageSeverity.Info, "Local call detected, aborting analysis of this branch.", nc);
                        }
                        else
                        {
                            report.AddMessage(ProjectReportMessage.MessageSeverity.Info, "Intermodular call detected, aborting analysis of this branch.", nc);
                        }
                    }
                    else if (node is NodeRet)
                    {
                        interpreter.Running = false;
                    }
                    else if (node is NodeResponseDialogue nrd)
                    {
                        var targetIndex = scene.Nodes.IndexOf(nrd.ResponseMap[0].Target);
                        if (targetIndex == -1)
                        {
                            report.AddMessage(ProjectReportMessage.MessageSeverity.Info, "Detected jump outside of current scope, aborting analysis of this branch.", nrd);
                            interpreter.Running = false;
                        }
                        interpreter.Position = targetIndex;

                        foreach (var response in nrd.ResponseMap.Skip(1))
                        {
                            var newState = new InterpreterState
                            {
                                Interpreter = (BranchingInterpreterVisitor)interpreter.Interpreter.Clone(),
                                Position    = scene.Nodes.IndexOf(response.Target),
                                Running     = true
                            };

                            if (newState.Position == -1)
                            {
                                report.AddMessage(ProjectReportMessage.MessageSeverity.Info, "Detected jump outside of current scope, aborting analysis of this branch.", nrd);
                            }
                            else
                            {
                                newStates.Add(newState);
                            }
                        }
                    }
                }

                _interpreters.AddRange(newStates);
            }
        }
        public async Task Interpret()
        {
            while (Running)
            {
                if (_scene.Nodes.Count == Position)
                {
                    Running = false;
                    return;
                }

                var node = _scene.Nodes[Position++];
                node.Accept(this);

                if (node is NodeCall nc)
                {
                    if (nc.Target == null)
                    {
                        continue;
                    }

                    var module = await WaitForModule(nc.Target);

                    var resultStates = module.States.FirstOrDefault(s => OutputState.Matches(s.Key)).Value;
                    if (resultStates == null)
                    {
                        Report.AddMessage(ProjectReportMessage.MessageSeverity.Error, "No overload for this call takes current state.", nc);
                        Running = false;
                        return;
                    }

                    OutputState.Merge(resultStates.First());

                    foreach (var outputState in resultStates.Skip(1))
                    {
                        var clone = Clone();
                        clone.OutputState.Merge(outputState);
                        _parent.AddInterpreter(clone);
                    }
                }
            }
        }