using System.Collections.Generic; using Newlon.Components.Plants; using Newlon.Systems.Effects; using Godot; using Newlon.Resources; namespace Newlon; public static class DescriptionParser { public static string GetParsed(EntityResource resource, Node searchScene) { string descriptionText; if (resource.isDescriptionParsed == false) { var unparsedDescription = TranslationServer.Translate(resource.DescriptionKey); var keys = GetRequestedKeys(unparsedDescription); FillPlaceholders(keys, resource, searchScene); ApplyModifiers(keys); descriptionText = ReplaceTextUsingDict(keys, unparsedDescription); resource.parsedDescription = descriptionText; resource.isDescriptionParsed = true; } else { descriptionText = resource.parsedDescription; } return descriptionText; } private static Dictionary GetRequestedKeys(string text) { var result = new Dictionary(); int start = -1; for (int i = 0; i < text.Length; i++) { if (text[i] == '{') { start = i; } if (text[i] == '}') { if (start == -1) continue; var substr = text.Substr(start + 1, i - start - 1); if (result.ContainsKey(substr) == false) result.Add(substr, 0); start = -1; } } return result; } public static void FillPlaceholders(Dictionary placeholderDictionary, EntityResource resource, Node searchScene) { var searchList = new List() { resource, searchScene }; while (searchList.Count > 0) { var lookedObject = searchList[0]; searchList.RemoveAt(0); if (lookedObject is Node lookedNode) searchList.AddRange(lookedNode.GetChildren()); if (lookedObject is Shooter shooter) { var projectile = shooter._projectile.Instantiate(); searchList.Add(projectile); } foreach (var property in lookedObject.GetPropertyList()) { if ((Variant.Type)property["type"].AsInt32() == Variant.Type.Object) { if (lookedObject.Get(property["name"].AsString()).AsGodotObject() is Effect effect) { searchList.Add(effect); } } } foreach (var key in placeholderDictionary.Keys) { string request = key.Split('|')[0]; var namePropertyPair = request.Split('.'); Variant property; if (namePropertyPair.Length == 2) { if ((namePropertyPair[0] == "?" && lookedObject != searchScene) || (namePropertyPair[0] != "?" && lookedObject is Node node && node.Name != namePropertyPair[0])) { continue; } property = lookedObject.Get(namePropertyPair[1]); } else { property = lookedObject.Get(namePropertyPair[0]); } if (property.VariantType == Variant.Type.Nil) { continue; } float value = property.As(); value = float.Round(value, 3); placeholderDictionary[key] = value; } } } public static void ApplyModifiers(Dictionary toDictionary) { foreach (var key in toDictionary.Keys) { if (key.Split('|').Length < 2) continue; string[] modifiers = key.Split('|')[1..]; float value = toDictionary[key]; for (int i = 0; i < modifiers.Length; i++) { if (modifiers[i] != "") { switch (modifiers[i][0]) { case '%': value *= 100; break; case '*': value *= GetNumberOrVar(1.0f); break; case '/': value /= GetNumberOrVar(1.0f); break; case '+': value += GetNumberOrVar(0.0f); break; case '-': value -= GetNumberOrVar(0.0f); break; } } float GetNumberOrVar(float defaultVal) { var contained = ContainsVariable(toDictionary, modifiers[i][1..]); if (contained != null) { return toDictionary[contained]; } else if (float.TryParse(modifiers[i][1..], out float mult)) { return mult; } return defaultVal; } } toDictionary[key] = value; } } public static string ContainsVariable(Dictionary dictionary, string variableName, bool ignoreParent = false) { foreach (var key in dictionary.Keys) { var keyAsVar = key.Split('|')[0]; if (ignoreParent) { if (keyAsVar.Split('.').Length == 2) { if (keyAsVar.Split('.')[1] == variableName) return key; } else if (keyAsVar == variableName) { return key; } } else { if (keyAsVar == variableName) { return key; } } } return null; } public static string ReplaceTextUsingDict(Dictionary dictionary, string text) { var resStr = text; foreach (var key in dictionary.Keys) { resStr = resStr.Replace('{' + key + '}', dictionary[key].ToString()); } return resStr; } }