newlon/scripts/systems/DescriptionParser.cs

198 lines
4.6 KiB
C#

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<string, float> GetRequestedKeys(string text)
{
var result = new Dictionary<string, float>();
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<string, float> placeholderDictionary, EntityResource resource, Node searchScene)
{
var searchList = new List<GodotObject>() { 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<float>();
value = float.Round(value, 3);
placeholderDictionary[key] = value;
}
}
}
public static void ApplyModifiers(Dictionary<string, float> 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<string, float> 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<string, float> dictionary, string text)
{
var resStr = text;
foreach (var key in dictionary.Keys)
{
resStr = resStr.Replace('{' + key + '}', dictionary[key].ToString());
}
return resStr;
}
}