/// <summary> /// Add a ScriptItem to the output buffer that will be consumed by the outside process (ie. World) /// </summary> /// <param name="output">ScripItem to add to queue</param> private void EnqueueToOutputBuffer(TalkScript.ScriptItem output) { lock (((ICollection)_outputBufferQueue).SyncRoot) { _outputBufferQueue.Enqueue(output); EnqueuedScriptItemCallback(this); } }
/// <summary> /// Simple converter that takes in a ScriptItem and returns a string /// </summary> /// <param name="item">item to process</param> /// <returns>string equivalent of the ScriptItem</returns> private string TextProcessItem(TalkScript.ScriptItem item) { switch (item.Command) { case TalkScript.TalkCommand.AvatarsName: return(_gameStateRef.AvatarsName); case TalkScript.TalkCommand.NewLine: return("\n"); case TalkScript.TalkCommand.PlainString: return(item.Str); case TalkScript.TalkCommand.Rune: _runeMode = !_runeMode; return(_runeMode ? " " : string.Empty); default: throw new Ultima5ReduxException("Passed in an unsupported TalkCommand: " + item.Command.ToString() + " to the TextProcessItem method"); } }
/// <summary> /// Process an individual line. /// The method evaluates each scriptitem within the line, adding items and text to the output buffer as required. /// Mega function /// </summary> /// <remarks>If you do not SPLIT the line ahead of time then it is going to act wonky...</remarks> /// <param name="scriptLine"></param> /// <param name="nTalkLineIndex"></param> /// <param name="nSplitLine"></param> /// <returns></returns> private async Task ProcessLine(TalkScript.ScriptLine scriptLine, int nTalkLineIndex, int nSplitLine) { // if they already know the avatar then they aren't going to ask again if (scriptLine.ContainsCommand(TalkScript.TalkCommand.AskName) && Npc.KnowTheAvatar) { _currentSkipInstruction = SkipInstruction.DontSkip; return; } int nItem = 0; int nItems = scriptLine.NumberOfScriptItems; do { TalkScript.ScriptItem item = scriptLine.GetScriptItem(nItem); // if this is the very first position of conversation // we must describe what we "see" if (nTalkLineIndex == (int)TalkScript.TalkConstants.Description && nSplitLine == 0 && nItem == 0) { EnqueueToOutputBuffer(new TalkScript.ScriptItem(TalkScript.TalkCommand.PlainString, GetConversationStr(DataOvlReference.ChunkPhrasesConversation.YOU_SEE) + " ")); } switch (item.Command) { case TalkScript.TalkCommand.IfElseKnowsName: Debug.Assert(nItems == 1); if (Npc.KnowTheAvatar) { // we continue to the next block, but skip the one after _currentSkipInstruction = SkipInstruction.SkipAfterNext; return; } else { // we skip the next block because it is the line used when we actually know the Avatar _currentSkipInstruction = SkipInstruction.SkipNext; return; } case TalkScript.TalkCommand.AvatarsName: // we should already know if they know the avatars name.... Debug.Assert(Npc.KnowTheAvatar); EnqueueToOutputBuffer(new TalkScript.ScriptItem(TalkScript.TalkCommand.PlainString, TextProcessItem(item))); break; case TalkScript.TalkCommand.AskName: EnqueueToOutputBuffer(new TalkScript.ScriptItem(TalkScript.TalkCommand.PlainString, GetConversationStr(DataOvlReference.ChunkPhrasesConversation.WHATS_YOUR_NAME))); EnqueueToOutputBuffer(item); // we actually wait in the function for the user to respond await AwaitResponse(); string avatarNameResponse = GetResponse(); // did they actually provide the Avatars name? if (avatarNameResponse.ToLower() == _gameStateRef.AvatarsName.ToLower()) { // i met them _gameStateRef.SetMetNPC(Npc); EnqueueToOutputBuffer(new TalkScript.ScriptItem(TalkScript.TalkCommand.PlainString, GetConversationStr(DataOvlReference.ChunkPhrasesConversation.PLEASURE))); break; } else { EnqueueToOutputBuffer(new TalkScript.ScriptItem(TalkScript.TalkCommand.PlainString, GetConversationStr(DataOvlReference.ChunkPhrasesConversation.IF_SAY_SO))); } break; case TalkScript.TalkCommand.CallGuards: EnqueueToOutputBuffer(item); break; case TalkScript.TalkCommand.Change: EnqueueToOutputBuffer(item); break; case TalkScript.TalkCommand.DefineLabel: // if I find a goto label, then i expect I have no further conversation lines left //Debug.Assert(nConversationIndex == conversationOrderScriptLines.Count - 1); // we are going to add the GotoLabel to the script _conversationOrder.Add((int)_script.GetScriptLineLabelIndex(item.LabelNum)); _conversationOrderScriptLines.Add(_script.GetScriptLine(_script.GetScriptLineLabelIndex(item.LabelNum))); _currentSkipInstruction = SkipInstruction.SkipToLabel; return; //return SkipInstruction.SkipToLabel; case TalkScript.TalkCommand.EndCoversation: EnqueueToOutputBuffer(item); ConversationEnded = true; break; case TalkScript.TalkCommand.Gold: EnqueueToOutputBuffer(item); break; case TalkScript.TalkCommand.JoinParty: if (_gameStateRef.IsFullParty()) { string noJoinResponse = GetConversationStr(DataOvlReference.ChunkPhrasesConversation.CANT_JOIN_1) + GetConversationStr(DataOvlReference.ChunkPhrasesConversation.CANT_JOIN_2); EnqueueToOutputBuffer(new TalkScript.ScriptItem(TalkScript.TalkCommand.PlainString, noJoinResponse)); //"Thou hast no room for me in thy party! Seek me again if one of thy members doth leave thee.\n")); } else { EnqueueToOutputBuffer(item); ConversationEnded = true; } break; case TalkScript.TalkCommand.KarmaMinusOne: EnqueueToOutputBuffer(item); break; case TalkScript.TalkCommand.KarmaPlusOne: EnqueueToOutputBuffer(item); break; case TalkScript.TalkCommand.KeyWait: EnqueueToOutputBuffer(item); break; case TalkScript.TalkCommand.NewLine: EnqueueToOutputBuffer(new TalkScript.ScriptItem(TalkScript.TalkCommand.PlainString, TextProcessItem(item))); break; case TalkScript.TalkCommand.Pause: EnqueueToOutputBuffer(item); break; case TalkScript.TalkCommand.PlainString: // we put it through the processor to change the text around if we are wrapped in a rune tag EnqueueToOutputBuffer(new TalkScript.ScriptItem(TalkScript.TalkCommand.PlainString, TextProcessItem(item))); break; case TalkScript.TalkCommand.Rune: EnqueueToOutputBuffer(new TalkScript.ScriptItem(TalkScript.TalkCommand.PlainString, TextProcessItem(item))); break; case TalkScript.TalkCommand.UserInputNotRecognized: EnqueueToOutputBuffer(new TalkScript.ScriptItem(TalkScript.TalkCommand.PlainString, GetConversationStr(DataOvlReference.ChunkPhrasesConversation.CANNOT_HELP) + "\n")); break; case TalkScript.TalkCommand.Unknown_Enter: break; case TalkScript.TalkCommand.DoNothingSection: // appears to signify an empty section break; case TalkScript.TalkCommand.StartLabelDefinition: // dirty - advance past the label that it will sink in... nItem++; break; case TalkScript.TalkCommand.Or: case TalkScript.TalkCommand.StartNewSection: throw new Ultima5ReduxException("We should never see the <OR> or <A2> code in conversation"); case TalkScript.TalkCommand.GotoLabel: break; case TalkScript.TalkCommand.PromptUserForInput_NPCQuestion: break; case TalkScript.TalkCommand.PromptUserForInput_UserInterest: break; default: throw new Ultima5ReduxException("Received TalkCommand I wasn't expecting during conversation"); } nItem++; // while we still have more items in the current split line } while (nItem < nItems); _currentSkipInstruction = SkipInstruction.DontSkip; return; //return SkipInstruction.DontSkip; }