Exemplo n.º 1
0
        /// <summary>
        /// After adding all elements, this will process the script into a more readable format
        /// </summary>
        public void InitScript()
        {
            // we keep track of the index into the ScriptLines all the way through the entire method
            int nIndex = END_BASE_INDEXES + 1;

            // have we encountered a label yet?

            //bool labelEncountered = false;

            string question;

            // we are going to add name, job and bye to all scripts by default. We use the QuestionAnswer objects to make it seamless
            List <string> nameQuestion = new List <string>(1)
            {
                "name"
            };

            _scriptQuestionAnswers.Add(new ScriptQuestionAnswer(nameQuestion, _scriptLines[(int)TalkConstants.Name]));
            List <string> jobQuestion = new List <string>(2)
            {
                "job", "work"
            };

            _scriptQuestionAnswers.Add(new ScriptQuestionAnswer(jobQuestion, _scriptLines[(int)TalkConstants.Job]));
            List <string> byeQuestion = new List <string>(1)
            {
                "bye"
            };

            _scriptQuestionAnswers.Add(new ScriptQuestionAnswer(byeQuestion, _scriptLines[(int)TalkConstants.Bye]));

            // repeat through the question/answer components until we hit a label - then we know to move onto the label section
            do
            {
                List <string> currQuestions = new List <string>();
                ScriptLine    line          = _scriptLines[nIndex];

                // if we just hit a label, then it's time to jump out of this loop and move onto the label reading loop
                if (line.GetScriptItem(0).Command == TalkCommand.StartLabelDefinition)
                {
                    //labelEncountered = true;
                    break;
                }

                // first time around we KNOW there is a first question, all NPCs have at least one question
                question = line.GetScriptItem(0).Str;

                // dumb little thing - there are some scripts that have the same keyword multiple times
                // the game favours the one it sees first (see "Camile" in West Brittany as an example)
                if (!_scriptQuestionAnswers.QuestionAnswers.ContainsKey(question))
                {
                    currQuestions.Add(question);
                }

                // if we peek ahead and the next command is an <or> then we will just skip it and continue to add to the questions list
                while (_scriptLines[nIndex + 1].ContainsCommand(TalkCommand.Or))
                {
                    nIndex  += 2;
                    line     = _scriptLines[nIndex];
                    question = line.GetScriptItem(0).Str;
                    // just in case they try to add the same question twice - this is kind of a bug in the data since the game just favours the first question it sees
                    if (!_scriptQuestionAnswers.QuestionAnswers.ContainsKey(question))
                    {
                        currQuestions.Add(question);
                    }
                }

                ScriptLine nextLine = _scriptLines[nIndex + 1];
                _scriptQuestionAnswers.Add(new ScriptQuestionAnswer(currQuestions, nextLine));
                nIndex += 2;
            } while (true);

            // a little hack - it's easy to end the conversation if it always ends with the end conversation tag
            _scriptLines[(int)TalkConstants.Bye].AddScriptItem(new ScriptItem(TalkCommand.EndCoversation));

            // time to process labels!! the nIndex that the previous routine left with is the beginning of the label section
            int count = 0;

            do // begin the label processing loop - pretty sure this is dumb and doesn't do anything - but everything messes up when I remove it
            {
                // this is technically a loop, but it should never actually loop. Kind of dumb, but fragile
                Debug.Assert(count++ == 0);

                ScriptLine line = _scriptLines[nIndex];
                ScriptLine nextLine;

                // if there are two script items, and those two script items identify an end of label section then let's break out
                // this should only actually occur if there are no labels at all
                if (line.NumberOfScriptItems == 2 && line.IsEndOfLabelSection)
                {
                    // all done. we either had no labels or reached the end of them
                    // assert that we are on the last line of the script
                    Debug.Assert(nIndex == _scriptLines.Count - 1);
                    break;
                }


                // i expect that this line will always indicate a new label is being defined
                Debug.Assert(line.GetScriptItem(0).Command == TalkCommand.StartLabelDefinition);

                // I don't like this, it's inelegant, but it works...
                // at this point we know:
                // This is a multi line message
                bool nextCommandDefaultMessage = false;

                do // called for each label #
                {
                    // Debug code for narrowing down to a single NPC
                    //if (scriptLines[0].GetScriptItem(0).Str.ToLower().Trim() == "sutek".ToLower())
                    //if (scriptLines[0].GetScriptItem(0).Str.ToLower().Trim() == "sir arbuthnot")
                    //{
                    //        Console.WriteLine("AH");
                    //}

                    line = _scriptLines[nIndex];

                    // let's make sure there are actually labels to look at
                    if (line.IsEndOfLabelSection)
                    {
                        nextCommandDefaultMessage = true;
                        break;
                    }

                    // create the shell for the label
                    ScriptTalkLabel scriptTalkLabel = new ScriptTalkLabel(line.GetScriptItem(1).LabelNum, line);

                    // save the new label to the label collection
                    _scriptTalkLabels.AddLabel(scriptTalkLabel);

                    // it's a single line only, so we skip this tom foolery below
                    if (_scriptLines[nIndex + 1].GetScriptItem(0).Command == TalkCommand.StartLabelDefinition)
                    {
                        // do nothing, the ScriptTalkLabel will simply have no DefaultAnswer indicating that only the primary label line is read

                        nIndex++;
                        continue;
                    }

                    // with a single answer below the label, we will always use the default answer
                    ScriptLine defaultAnswer = _scriptLines[++nIndex];
                    scriptTalkLabel.DefaultAnswers.Add(defaultAnswer);

                    // it's a default only answer, and no additional line of dialog, then we skip this tom foolery below
                    if (_scriptLines[nIndex + 1].GetScriptItem(0).Command == TalkCommand.StartLabelDefinition)
                    {
                        nIndex++;
                        continue;
                    }

                    do // go through the question/answer and <or>
                    {
                        // Debug code to stop at given index
                        //if (nIndex == 22) { Console.WriteLine(""); }

                        List <string> currQuestions = new List <string>();
                        // if the next line is an <or> then process the <or>
                        if (_scriptLines[nIndex + 2].ContainsCommand(TalkCommand.Or))
                        {
                            while (_scriptLines[nIndex + 2].ContainsCommand(TalkCommand.Or))
                            {
                                line = _scriptLines[nIndex + 1];
                                Debug.Assert(line.IsQuestion);
                                question = line.GetScriptItem(0).Str;
                                // just in case they try to add the same question twice - this is kind of a bug in the data since the game just favours the first question it sees
                                if (!_scriptQuestionAnswers.QuestionAnswers.ContainsKey(question))
                                {
                                    currQuestions.Add(question);
                                }
                                nIndex += 2;
                            }
                            line = _scriptLines[++nIndex];
                            Debug.Assert(line.IsQuestion);
                            question = line.GetScriptItem(0).Str;
                            // just in case they try to add the same question twice - this is kind of a bug in the data since the game just favours the first question it sees
                            if (!_scriptQuestionAnswers.QuestionAnswers.ContainsKey(question))
                            {
                                currQuestions.Add(question);
                            }
                        }
                        // is this a question that the player would ask an NPC?
                        else if (_scriptLines[nIndex + 1].GetScriptItem(0).IsQuestion())
                        {
                            // get the Avatar's response line
                            line = _scriptLines[++nIndex];

                            question = line.GetScriptItem(0).Str;
                            Debug.Assert(ScriptItem.IsQuestion(question));
                            currQuestions.Add(question);
                        }
                        // the NPC has tricked me - this is a second line of dialog for the given
                        // that dastardly LB has put an extra response line in....
                        else //if (scriptLines[nIndex + 1].GetScriptItem(0).Str.Trim().Length > 4)
                        {
                            line = _scriptLines[++nIndex];
                            Debug.Assert(!line.IsQuestion);
                            scriptTalkLabel.DefaultAnswers.Add(line);
                            nIndex++;
                            // let's make double sure that we only have a single additional line of text
                            Debug.Assert(_scriptLines[nIndex].GetScriptItem(0).Command == TalkCommand.StartLabelDefinition);

                            nextLine = _scriptLines[nIndex];
                            continue;
                        }

                        // get your answer and store it
                        ScriptLine npcResponse = _scriptLines[++nIndex];
                        // we are ready to create a Q&A object and add it the label specific Q&A script
                        scriptTalkLabel.AddScriptQuestionAnswer(new ScriptQuestionAnswer(currQuestions, npcResponse));

                        // we are at the end of the label section of the file, so we are done.
                        nextLine = _scriptLines[++nIndex];

                        // does the next line indicate end of all of the label sections, then let's get out of this loop
                        if (nextLine.IsEndOfLabelSection)
                        {
                            nIndex--;
                            nextCommandDefaultMessage = true;
                            break;
                        }
                        // is the next line a label definition? is so, let's exit this label and move on
                        if (!nextLine.IsLabelDefinition())
                        {
                            nIndex--;
                            continue;
                        }

                        // while we know the next line is not a new label or end of label, then let's keep reading by moving to our next loop
                    } while (nextLine.GetScriptItem(0).Command != TalkCommand.StartLabelDefinition);
                    // while we haven't encountered an end of label section
                } while (!nextCommandDefaultMessage);

                nIndex++;
                // while we haven't read every last line, then let's keep reading
            } while (nIndex < (_scriptLines.Count - 1));
        }
Exemplo n.º 2
0
 /// <summary>
 /// Add a single ScriptTalkLabel
 /// </summary>
 /// <param name="talkLabel"></param>
 public void AddLabel(ScriptTalkLabel talkLabel)
 {
     Labels.Add(talkLabel);
 }