/// <summary> /// Gets the entrytag string of a dialogue entry. /// </summary> /// <param name="conversation">Dialogue entry's conversation.</param> /// <param name="entry">Dialogue entry.</param> /// <param name="entrytagFormat">Entrytag format.</param> /// <returns>Entrytag.</returns> public string GetEntrytag(Conversation conversation, DialogueEntry entry, EntrytagFormat entrytagFormat) { if (conversation == null || entry == null) { return(InvalidEntrytag); } Actor actor = null; Regex regex = new Regex("[;:,!\'\"\t\r\n\\/\\?\\[\\] ]"); switch (entrytagFormat) { case EntrytagFormat.ActorName_ConversationID_EntryID: actor = GetActor(entry.ActorID); if (actor == null) { return(InvalidEntrytag); } return(string.Format("{0}_{1}_{2}", regex.Replace(actor.Name, "_"), conversation.id, entry.id)); case EntrytagFormat.ConversationTitle_EntryID: return(string.Format("{0}_{1}", regex.Replace(conversation.Title, "_"), entry.id)); case EntrytagFormat.ActorNameLineNumber: actor = GetActor(entry.ActorID); if (actor == null) { return(InvalidEntrytag); } int lineNumber = (conversation.id * 500) + entry.id; return(string.Format("{0}{1}", new Regex("[,\"\t\r\n\\/<>?]").Replace(actor.Name, "_"), lineNumber)); case EntrytagFormat.ConversationID_ActorName_EntryID: actor = GetActor(entry.ActorID); if (actor == null) { return(InvalidEntrytag); } return(string.Format("{0}_{1}_{2}", conversation.id, regex.Replace(actor.Name, "_"), entry.id)); case EntrytagFormat.ActorName_ConversationTitle_EntryDescriptor: actor = GetActor(entry.ActorID); if (actor == null) { return(InvalidEntrytag); } var entryDesc = !string.IsNullOrEmpty(entry.Title) ? entry.Title : (!string.IsNullOrEmpty(entry.currentMenuText) ? entry.currentMenuText : entry.id.ToString()); return(string.Format("{0}_{1}_{2}", regex.Replace(actor.Name, "_"), regex.Replace(conversation.Title, "_"), regex.Replace(entryDesc, "_"))); case EntrytagFormat.VoiceOverFile: return((entry == null) ? InvalidEntrytag : Field.LookupValue(entry.fields, VoiceOverFileFieldName)); default: return(InvalidEntrytag); } }
// Consider which actors are new and which must be removed private void PrepareActors(List <ActorState> actorStates, out bool mustChangeArrangement) { _removedActorsIndices.Clear(); mustChangeArrangement = false; foreach (var actorState in actorStates) { if (!Field.FieldExists(actorState.fields, ActorArrangementActionFieldName)) { continue; } string actionTypeString = Field.LookupValue(actorState.fields, ActorArrangementActionFieldName); ActorArrangementActionType actionType = (ActorArrangementActionType)Enum.Parse(typeof(ActorArrangementActionType), actionTypeString); // Manage actor infos switch (actionType) { case ActorArrangementActionType.None: break; case ActorArrangementActionType.ChangePosition: if (!_actorIdToIndex.ContainsKey(actorState.ActorID)) { AddActor(actorState.ActorID); mustChangeArrangement = true; } Assert.IsTrue(_actorIdToIndex.ContainsKey(actorState.ActorID), "Arrangement with type 'changePosition' is applied to the absent actor"); ActorInfo actorInfo = _allActors[_actorIdToIndex[actorState.ActorID]]; Assert.IsTrue(Field.FieldExists(actorState.fields, PositionTypeFieldName), "Actor state doesn't have Position Type field when it's needed"); string positionTypeString = Field.LookupValue(actorState.fields, PositionTypeFieldName); ActorScreenPositionType positionType = (ActorScreenPositionType)Enum.Parse(typeof(ActorScreenPositionType), positionTypeString); if (actorInfo.PositionType != positionType) { mustChangeArrangement = true; } // Update actorInfo actorInfo.PositionType = positionType; break; case ActorArrangementActionType.Leave: DeleteActor(actorState.ActorID); mustChangeArrangement = true; break; default: Assert.IsTrue(false); break; } } }
private static void ExportConversations(DialogueDatabase database, string language, EntrytagFormat entrytagFormat, StreamWriter file) { file.WriteLine(string.Empty); file.WriteLine("---Conversations---"); // Cache actor names: Dictionary <int, string> actorNames = new Dictionary <int, string>(); // Export all conversations: foreach (var conversation in database.conversations) { file.WriteLine(string.Empty); file.WriteLine(string.Format("Conversation {0},{1}", conversation.id, CleanField(conversation.Title))); file.WriteLine(string.Format("Description,{0}", CleanField(conversation.Description))); StringBuilder sb = new StringBuilder("entrytag,Actor,Description,"); sb.Append(string.IsNullOrEmpty(language) ? "Dialogue Text" : CleanField(language)); file.WriteLine(sb.ToString()); foreach (var entry in conversation.dialogueEntries) { if (entry.id > 0) { sb = new StringBuilder(); if (!actorNames.ContainsKey(entry.ActorID)) { Actor actor = database.GetActor(entry.ActorID); actorNames.Add(entry.ActorID, (actor != null) ? CleanField(actor.Name) : "ActorNotFound"); } string actorName = actorNames[entry.ActorID]; string description = Field.LookupValue(entry.fields, "Description"); string entrytag = database.GetEntrytag(conversation, entry, entrytagFormat); var lineText = string.IsNullOrEmpty(language) ? entry.subtitleText : Field.LookupValue(entry.fields, language); sb.AppendFormat("{0},{1},{2},{3}", CleanField(entrytag), CleanField(actorName), CleanField(description), CleanField(lineText)); file.WriteLine(sb.ToString()); } } } }
private static void ExportSubtree(DialogueDatabase database, string language, Dictionary <int, string> actorNames, Dictionary <int, int> numLinksToEntry, List <DialogueEntry> visited, DialogueEntry entry, int siblingIndex, StreamWriter file) { if (entry == null) { return; } visited.Add(entry); if (entry.id > 0) { var omit = omitNoneOrContinueEntries && (entry.Sequence == "None()" || entry.Sequence == "Continue()"); var show = !omit; // Write this entry (the root of the subtree). // Write entry ID if necessary: if (siblingIndex == -1) { if (show) { file.WriteLine(string.Format("\tUnconnected entry [{0}]:", entry.id)); } if (show) { file.WriteLine(string.Empty); } } else if ((siblingIndex == 0 && !string.IsNullOrEmpty(entry.conditionsString)) || (siblingIndex > 0) || (numLinksToEntry.ContainsKey(entry.id) && numLinksToEntry[entry.id] > 1)) { if (string.IsNullOrEmpty(entry.conditionsString)) { if (show) { file.WriteLine(string.Format("\tEntry [{0}]:", entry.id)); } } else { if (show) { file.WriteLine(string.Format("\tEntry [{0}]: ({1})", entry.id, entry.conditionsString)); } } if (show) { file.WriteLine(string.Empty); } } if (!actorNames.ContainsKey(entry.ActorID)) { Actor actor = database.GetActor(entry.ActorID); actorNames.Add(entry.ActorID, (actor != null) ? actor.Name.ToUpper() : "ACTOR"); } if (show) { file.WriteLine(string.Format("\t\t\t\t{0}", actorNames[entry.ActorID])); } var description = Field.LookupValue(entry.fields, "Description"); if (!string.IsNullOrEmpty(description)) { if (show) { file.WriteLine(string.Format("\t\t\t({0})", description)); } } var lineText = string.IsNullOrEmpty(language) ? entry.subtitleText : Field.LookupValue(entry.fields, language); if (entry.isGroup) { // Group entries use Title: lineText = Field.LookupValue(entry.fields, "Title"); lineText = !string.IsNullOrEmpty(lineText) ? ("(" + lineText + ")") : "(Group entry; no dialogue)"; } if (show) { file.WriteLine(string.Format("\t\t{0}", lineText)); } if (show) { file.WriteLine(string.Empty); } } // Handle link summary: if (entry.outgoingLinks.Count == 0) { file.WriteLine("\t\t\t\t[END]"); file.WriteLine(string.Empty); } else if (entry.outgoingLinks.Count > 1) { var s = "\tResponses: "; var first = true; for (int i = 0; i < entry.outgoingLinks.Count; i++) { if (!first) { s += ", "; } first = false; var link = entry.outgoingLinks[i]; if (link.destinationConversationID == entry.conversationID) { s += "[" + link.destinationDialogueID + "]"; } else { var destConversation = database.GetConversation(link.destinationConversationID); if (destConversation != null) { s += "[" + destConversation.Title.ToUpper() + ":" + link.destinationDialogueID + "]"; } else { s += "[Other Conversation]"; } } } file.WriteLine(s); file.WriteLine(string.Empty); } // Follow each outgoing link as a subtree: for (int i = 0; i < entry.outgoingLinks.Count; i++) { var child = database.GetDialogueEntry(entry.outgoingLinks[i]); if (!visited.Contains(child)) { ExportSubtree(database, language, actorNames, numLinksToEntry, visited, child, i, file); } } }
/// <summary> /// Looks up the value of a field. /// </summary> /// <returns> /// The string value of the field with the specified title, or <c>null</c> if no field /// matches. /// </returns> /// <param name='title'> /// The title of the field to look up. /// </param> public string LookupValue(string title) { return(Field.LookupValue(fields, title)); }
private static void ExpandCompressedSimStatusData() { if (!(includeSimStatus && DialogueManager.instance.includeSimStatus)) { return; } try { var useConversationID = string.IsNullOrEmpty(saveConversationSimStatusWithField); var useEntryID = string.IsNullOrEmpty(saveDialogueEntrySimStatusWithField); var entryDict = new Dictionary <string, DialogueEntry>(); foreach (var conversation in DialogueManager.masterDatabase.conversations) { // If saving dialogue entries' SimStatus with value of a field, make a lookup table: if (!useEntryID) { entryDict.Clear(); for (int i = 0; i < conversation.dialogueEntries.Count; i++) { var entry = conversation.dialogueEntries[i]; var entryFieldValue = Field.LookupValue(entry.fields, saveDialogueEntrySimStatusWithField); if (!entryDict.ContainsKey(entryFieldValue)) { entryDict.Add(entryFieldValue, entry); } } } var sb = new StringBuilder(); string simX; if (useConversationID) { simX = Lua.Run("return Conversation[" + conversation.id + "].SimX").asString; } else { var fieldValue = DialogueLua.StringToTableIndex(conversation.LookupValue(saveConversationSimStatusWithField)); if (string.IsNullOrEmpty(fieldValue)) { fieldValue = conversation.id.ToString(); } simX = Lua.Run("return Variable[\"Conversation_SimX_" + fieldValue + "\"]").asString; } if (string.IsNullOrEmpty(simX) || string.Equals(simX, "nil")) { continue; } var clearSimXCommand = useConversationID ? ("Conversation[" + conversation.id + "].SimX=nil;") : ("Variable[\"Conversation_SimX_" + DialogueLua.StringToTableIndex(conversation.LookupValue(saveConversationSimStatusWithField)) + "\"]=nil;"); sb.Append("Conversation["); sb.Append(conversation.id); sb.Append("].Dialog={}; "); var simXFields = simX.Split(';'); var numFields = simXFields.Length / 2; for (int i = 0; i < numFields; i++) { var simXEntryIDValue = simXFields[2 * i]; string entryID; if (useEntryID) { entryID = simXEntryIDValue; } else { entryID = entryDict.ContainsKey(simXEntryIDValue) ? entryDict[simXEntryIDValue].id.ToString() : "-1"; } var simStatus = CharToSimStatus(simXFields[(2 * i) + 1][0]); sb.Append("Conversation["); sb.Append(conversation.id); sb.Append("].Dialog["); sb.Append(entryID); sb.Append("]={SimStatus='"); sb.Append(simStatus); sb.Append("'}; "); } sb.Append(clearSimXCommand); Lua.Run(sb.ToString()); } } catch (System.Exception e) { Debug.LogError(string.Format("{0}: ApplySaveData() failed to re-expand compressed SimStatus data: {1}", new System.Object[] { DialogueDebug.Prefix, e.Message })); } }
/// <summary> /// Appends the conversation table to a (saved-game) string. To conserve space, only the /// SimStatus is recorded. If includeSimStatus is <c>false</c>, nothing is recorded. /// The exception is if includeAllConversationFields is true. /// </summary> public static void AppendConversationData(StringBuilder sb) { if (includeAllConversationFields || DialogueManager.instance.persistentDataSettings.includeAllConversationFields) { AppendAllConversationFields(sb); } if (!(includeSimStatus && DialogueManager.instance.includeSimStatus)) { return; } try { #if USE_NLUA var useConversationID = string.IsNullOrEmpty(saveConversationSimStatusWithField); var useEntryID = string.IsNullOrEmpty(saveDialogueEntrySimStatusWithField); foreach (var conversation in DialogueManager.MasterDatabase.conversations) { if (useConversationID) { sb.AppendFormat("Conversation[{0}].SimX=\"", conversation.id); } else { var fieldValue = DialogueLua.StringToTableIndex(conversation.LookupValue(saveConversationSimStatusWithField)); if (string.IsNullOrEmpty(fieldValue)) { fieldValue = conversation.id.ToString(); } sb.AppendFormat("Variable[\"Conversation_SimX_{0}\"]=\"", fieldValue); } var dialogTable = Lua.Run("return Conversation[" + conversation.id + "].Dialog").AsLuaTable; var first = true; for (int i = 0; i < conversation.dialogueEntries.Count; i++) { var entry = conversation.dialogueEntries[i]; var entryID = entry.id; var dialogFields = dialogTable[entryID] as NLua.LuaTable; if (dialogFields != null) { if (!first) { sb.Append(";"); } first = false; sb.Append(useEntryID ? entryID.ToString() : Field.LookupValue(entry.fields, saveDialogueEntrySimStatusWithField)); sb.Append(";"); var simStatus = dialogFields["SimStatus"].ToString(); sb.Append(SimStatusToChar(simStatus)); } } sb.Append("\"; "); } #else var useConversationID = string.IsNullOrEmpty(saveConversationSimStatusWithField); var useEntryID = string.IsNullOrEmpty(saveDialogueEntrySimStatusWithField); foreach (var conversation in DialogueManager.masterDatabase.conversations) { if (useConversationID) { sb.AppendFormat("Conversation[{0}].SimX=\"", conversation.id); } else { sb.AppendFormat("Variable[\"Conversation_SimX_{0}\"]=\"", DialogueLua.StringToTableIndex(conversation.LookupValue(saveConversationSimStatusWithField))); } var conversationTable = Lua.Run("return Conversation[" + conversation.id + "]").asTable; var dialogTable = conversationTable.luaTable.GetValue("Dialog") as Language.Lua.LuaTable; var first = true; for (int i = 0; i < conversation.dialogueEntries.Count; i++) { var entry = conversation.dialogueEntries[i]; var entryID = entry.id; var dialogFields = dialogTable.GetValue(entryID) as Language.Lua.LuaTable; if (dialogFields != null) { if (!first) { sb.Append(";"); } first = false; sb.Append(useEntryID ? entryID.ToString() : Field.LookupValue(entry.fields, saveDialogueEntrySimStatusWithField)); sb.Append(";"); var simStatus = dialogFields.GetValue("SimStatus").ToString(); sb.Append(SimStatusToChar(simStatus)); } } sb.Append("\"; "); } #endif } catch (System.Exception e) { Debug.LogError(string.Format("{0}: GetSaveData() failed to get conversation data: {1}", new System.Object[] { DialogueDebug.Prefix, e.Message })); } }