extends Node class_name DialogicParser static func parse_characters(dialog_script): var characters = DialogicUtil.get_character_list() var event_index: = 0 if dialog_script.size() == 0: return dialog_script; for event in dialog_script["events"]: if event.get("event_id") in ["dialogic_001", "dialogic_010"]: var text:String = event.get({"dialogic_001":"text", "dialogic_010":"question"}[event.get("event_id")], "") if event.has("question"): event["originalText"] = event["question"] for character in characters: var char_names = [character.get("name")] if character.get("data", {}).get("display_name_bool", false): if character.get("display_name"):char_names.append(character.get("display_name")) if character.get("data", {}).get("nickname_bool", false): for nickname in character.get("data").get("nickname", "").split(",", true, 0): if nickname.strip_edges(): char_names.append(nickname.strip_edges()) var escapeRegExp = "(?=[+&|!(){}^\"~*.?:\\\\-])" var regex = RegEx.new() regex.compile(escapeRegExp) char_names = regex.sub(str(char_names), "\\", true) var regex_thing = "((\\]|^)[^\\[]*)(?" + str(char_names).replace("[", "(").replace("]", ")").replace(", ", "|") + ")" regex.compile(regex_thing) var counter = 0 for result in regex.search_all(text): text = text.insert(result.get_start("name") + ((9 + 8 + 8) * counter), "[color=#" + character["color"].to_html() + "]") text = text.insert(result.get_end("name") + 9 + 8 + ((9 + 8 + 8) * counter), "[/color]") result = regex.search(text) counter += 1 dialog_script["events"][event_index][{"dialogic_001":"text", "dialogic_010":"question"}[event.get("event_id")]] = text event_index += 1 return dialog_script static func parse_text_lines(unparsed_dialog_script:Dictionary, preview:bool = false)->Dictionary: var parsed_dialog:Dictionary = unparsed_dialog_script var new_events:Array = [] var settings = DialogicResources.get_settings_config() var split_new_lines = settings.get_value("dialog", "new_lines", true) var remove_empty_messages = settings.get_value("dialog", "remove_empty_messages", true) var alreadySeen = false; var originalText = ""; if unparsed_dialog_script.has("events") == false: return unparsed_dialog_script for event in unparsed_dialog_script["events"]: alreadySeen = false; originalText = ""; if event.has("text"): originalText = event["text"]; alreadySeen = SeenTextSingleton.CheckIfSeen(event["text"]); event["text"] = TranslationServer.tr(event["text"]) if event.has("text") and event.has("character") and event.has("portrait"): if event["text"].empty() and remove_empty_messages: pass elif "\n" in event["text"] and preview == false and split_new_lines: var lines = event["text"].split("\n") var counter = 0 for line in lines: if not line.empty(): var n_event = { "event_id":"dialogic_001", "text":line, "character":event["character"], "portrait":event["portrait"], "seen":alreadySeen, "originalText":originalText, } if event.has("voice_data"): if event["voice_data"].has(str(counter)): n_event["voice_data"] = {"0":event["voice_data"][str(counter)]} new_events.append(n_event) counter += 1 else : event["seen"] = alreadySeen event["originalText"] = originalText new_events.append(event) else : new_events.append(event) parsed_dialog["events"] = new_events return parsed_dialog static func parse_definitions(current_dialog, text:String, variables:bool = true, glossary:bool = true): var final_text:String = text if not current_dialog.preview: current_dialog.definitions = Dialogic._get_definitions() if variables: final_text = _insert_variable_definitions(current_dialog, text) if glossary and current_dialog._should_show_glossary(): final_text = _insert_glossary_definitions(current_dialog, final_text) return final_text static func parse_branches(current_dialog, dialog_script:Dictionary)->Dictionary: current_dialog.questions = [] if dialog_script.has("events") == false: return dialog_script var parser_queue = [] var event_idx:int = 0 var question_idx:int = 0 for event in dialog_script["events"]: if event["event_id"] == "dialogic_011": var opened_branch = parser_queue.back() event["choice"] = TranslationServer.tr(event["choice"]) var option = { "question_idx":opened_branch["question_idx"], "label":parse_definitions(current_dialog, event["choice"], true, false), "event_idx":event_idx, } if event.has("condition") and event.has("definition") and event.has("value"): option = { "question_idx":opened_branch["question_idx"], "label":parse_definitions(current_dialog, event["choice"], true, false), "event_idx":event_idx, "condition":event["condition"], "definition":event["definition"], "value":event["value"], } else : option = { "question_idx":opened_branch["question_idx"], "label":parse_definitions(current_dialog, event["choice"], true, false), "event_idx":event_idx, "condition":"", "definition":"", "value":"", } dialog_script["events"][opened_branch["event_idx"]]["options"].append(option) event["question_idx"] = opened_branch["question_idx"] elif event["event_id"] == "dialogic_010": event["event_idx"] = event_idx event["question_idx"] = question_idx event["answered"] = false question_idx += 1 current_dialog.questions.append(event) parser_queue.append(event) elif event["event_id"] == "dialogic_012": event["event_idx"] = event_idx event["question_idx"] = question_idx event["answered"] = false question_idx += 1 current_dialog.questions.append(event) parser_queue.append(event) elif event["event_id"] == "dialogic_013" and parser_queue: event["event_idx"] = event_idx var opened_branch = parser_queue.pop_back() event["end_branch_of"] = opened_branch["question_idx"] dialog_script["events"][opened_branch["event_idx"]]["end_idx"] = event_idx event_idx += 1 return dialog_script static func parse_anchors(current_dialog): current_dialog.anchors = {} var idx = 0 if current_dialog.dialog_script.size() != 0: for event in current_dialog.dialog_script["events"]: if event["event_id"] == "dialogic_015": current_dialog.anchors[event["id"]] = idx idx += 1 static func parse_alignment(current_dialog, text): var alignment = current_dialog.current_theme.get_value("text", "alignment", 0) var fname = current_dialog.current_theme.get_value("settings", "name", "none") if alignment in [1, 4, 7]: text = "[center]" + text + "[/center]" elif alignment in [2, 5, 8]: text = "[right]" + text + "[/right]" return text static func _insert_variable_definitions(current_dialog, text:String): var final_text: = text; var regex = RegEx.new() regex.compile("\\[(.*?)\\]") var result = regex.search_all(final_text) if result: for res in result: var r_string = res.get_string() if "," in r_string: var r_string_array = r_string.replace("[", "").replace("]", "").split(",") var new_word = r_string_array[randi() % r_string_array.size()] for d in current_dialog.definitions["variables"]: var name:String = d["name"] if new_word == d["name"]: new_word = str(d["value"]) final_text = final_text.replace(r_string, new_word) else : var r_string_array = r_string.replace("[", "").replace("]", "") if "/" in r_string_array: var variable_id = Dialogic._get_variable_from_file_name(r_string_array) for d in current_dialog.definitions["variables"]: if d["id"] == variable_id: final_text = final_text.replace(r_string, d["value"]) else : for d in current_dialog.definitions["variables"]: if d["name"] == r_string_array: final_text = final_text.replace(r_string, d["value"]) var declensionRegex = RegEx.new(); declensionRegex.compile("\\~(.*?)\\~"); var declRes = declensionRegex.search_all(final_text); if declRes: for res in declRes: var r_string = res.get_string() var temp = r_string.replace("~", ""); var value = DeclinationText(temp); final_text = final_text.replace(r_string, value) return final_text static func DeclinationText(temp:String)->String: var type = temp[0]; match type: "р": temp = ToRodit(temp) "д": temp = ToDat(temp) "в": temp = ToVinit(temp) "т": temp = ToTvorit(temp) "п": temp = ToPredlog(temp) var value = temp.substr(1); return value; static func ToRodit(string:String)->String: if string.ends_with("а"): string = string.trim_suffix("а") string += "ы" elif string.ends_with("я"): string = string.trim_suffix("я") string += "и" elif string.ends_with("и"): pass elif (string.ends_with("р") or string.ends_with("н") or string.ends_with("т")): string += "а" return string static func ToDat(string:String)->String: if string.ends_with("а"): string = string.trim_suffix("а") string += "е" elif string.ends_with("я"): string = string.trim_suffix("я") string += "и" elif string.ends_with("и"): pass elif (string.ends_with("р") or string.ends_with("н") or string.ends_with("т")): string += "у" return string static func ToVinit(string:String)->String: if string.ends_with("а"): string = string.trim_suffix("а") string += "у" elif string.ends_with("я"): string = string.trim_suffix("я") string += "ю" elif string.ends_with("и"): pass elif (string.ends_with("р") or string.ends_with("н") or string.ends_with("т")): string += "а" return string static func ToTvorit(string:String)->String: if string.ends_with("а"): string = string.trim_suffix("а") string += "ой" elif string.ends_with("я"): string = string.trim_suffix("я") string += "ей" elif string.ends_with("и"): pass elif (string.ends_with("р") or string.ends_with("н") or string.ends_with("т")): string += "ом" return string static func ToPredlog(string:String)->String: if string.ends_with("а"): string = string.trim_suffix("а") string += "е" elif string.ends_with("я"): string = string.trim_suffix("я") string += "и" elif string.ends_with("и"): pass elif (string.ends_with("р") or string.ends_with("н") or string.ends_with("т")): string += "е" return string static func _insert_glossary_definitions(current_dialog, text:String): var color = current_dialog.current_theme.get_value("definitions", "color", "#ffbebebe") var final_text: = text for d in current_dialog.definitions["glossary"]: final_text = final_text.replace(d["name"], "[url=" + d["id"] + "]" + "[color=" + color + "]" + d["name"] + "[/color]" + "[/url]" ) return final_text