Files
Continentis/Assets/Scripts/MainGame/Card/CardSubmodules/CardDescriptionInterpreter.cs
SoulliesOfficial 9b1b5ca93f initial
2025-10-03 00:02:43 -04:00

249 lines
9.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Globalization;
using DynamicExpresso;
using UnityEngine;
namespace Continentis.MainGame.Card
{
public static partial class CardDescriptionInterpreter
{
public static Interpreter DescriptionInterpreter;
static CardDescriptionInterpreter()
{
DescriptionInterpreter = new Interpreter();
DescriptionInterpreter.SetFunction("GetDynamicValue", new Func<float, float, bool, string>(GetDynamicValue));
DescriptionInterpreter.SetFunction("GetDynamicValue", new Func<float, string>(GetDynamicValue));
DescriptionInterpreter.SetFunction("AttributeCheck", new Func<string, float, float, string>(AttributeCheck));
foreach (KeyValuePair<string,string> keyword in CombatMainManager.Instance.keywordCollection.keywords)
{
DescriptionInterpreter.SetVariable(keyword.Key, keyword.Key);
}
foreach (KeyValuePair<string, InterpretedKeyword> keyword in CombatMainManager.Instance.keywordCollection.interpretedKeywords)
{
DescriptionInterpreter.SetVariable(keyword.Key, keyword.Value.name);
}
}
public static string InterpretDescription(CardLogicBase card)
{
card.contentSubmodule.keywords.Clear();
foreach (KeyValuePair<string, float> attribute in card.attributeSubmodule.attributeGroup.current)
{
DescriptionInterpreter.SetVariable(attribute.Key, attribute.Value);
}
DescriptionInterpreter.SetFunction("RemoveWhenSelecting", new Func<string, string>((toRemove) => RemoveWhenSelecting(card, toRemove)));
string result = ParseKeywords(card.cardData.cardDescription, card.contentSubmodule.keywords);
card.contentSubmodule.cardDescription = result;
Debug.Log($"Interpreted Description: {result}");
return result;
}
}
public partial class CardDescriptionInterpreter
{
public static List<string> GetKeywords(string template)
{
List<string> keywords = new List<string>();
DescriptionInterpreter.UnsetExpression("Keyword");
DescriptionInterpreter.SetFunction("Keyword", new Action<string>((keywordName) =>
{
if (!string.IsNullOrEmpty(keywordName) && !keywords.Contains(keywordName))
{
keywords.Add(keywordName);
}
}));
try
{
//提取所有$Keyword(...)的关键词
//其它的表达式直接跳过
while (template.Contains("$"))
{
int startIndex = template.LastIndexOf('$');
int endIndex = FindMatchingClosingParenthesis(template, startIndex);
if (endIndex == -1)
{
Debug.LogError($"解析错误: 在 '{template}' 中找不到与 '{template.Substring(startIndex)}' 匹配的闭合括号。");
break; // 中断以防止死循环
}
string expressionToEvaluate = template.Substring(startIndex, endIndex - startIndex + 1);
string cleanExpression = expressionToEvaluate.Substring(1);
// 仅处理 Keyword 函数,跳过其他表达式
if (cleanExpression.StartsWith("Keyword"))
{
DescriptionInterpreter.Eval(cleanExpression);
}
// 移除已处理的表达式,继续查找下一个
template = template.Substring(0, startIndex) + template.Substring(endIndex + 1);
}
}
catch (Exception ex)
{
throw new Exception($"解析模板时发生严重错误: {ex.Message}\nStackTrace: {ex.StackTrace}");
}
return keywords;
}
public static string ParseKeywords(string template, List<string> keywords)
{
DescriptionInterpreter.UnsetExpression("Keyword");
DescriptionInterpreter.SetFunction("Keyword", new Func<string, string>((keywordName) =>
{
if (!string.IsNullOrEmpty(keywordName) && !keywords.Contains(keywordName))
{
keywords.Add(keywordName);
}
return Keyword(keywordName);
}));
try
{
while (template.Contains("$"))
{
int startIndex = template.LastIndexOf('$');
int endIndex = FindMatchingClosingParenthesis(template, startIndex);
if (endIndex == -1)
{
Debug.LogError($"解析错误: 在 '{template}' 中找不到与 '{template.Substring(startIndex)}' 匹配的闭合括号。");
return template; // 中断以防止死循环
}
string expressionToEvaluate = template.Substring(startIndex, endIndex - startIndex + 1);
string cleanExpression = expressionToEvaluate.Substring(1);
object result = DescriptionInterpreter.Eval(cleanExpression);
string resultAsLiteral = result.ToString();
template = template.Substring(0, startIndex) + resultAsLiteral + template.Substring(endIndex + 1);
}
}
catch (Exception ex)
{
throw new Exception($"解析模板时发生严重错误: {ex.Message}\nStackTrace: {ex.StackTrace}");
}
return template;
}
private static int FindMatchingClosingParenthesis(string text, int startIndex)
{
int openParenIndex = text.IndexOf('(', startIndex);
if (openParenIndex == -1) return -1;
int parenthesisCounter = 1;
bool isInString = false;
for (int i = openParenIndex + 1; i < text.Length; i++)
{
char c = text[i];
char prevC = i > 0 ? text[i - 1] : '\0';
// 检查是否进入或退出字符串(忽略转义的引号 \"
if (c == '"' && prevC != '\\')
{
isInString = !isInString;
}
// 如果在字符串中,则跳过对括号的计数
if (isInString)
{
continue;
}
if (c == '(')
{
parenthesisCounter++;
}
else if (c == ')')
{
parenthesisCounter--;
}
if (parenthesisCounter == 0)
{
return i;
}
}
return -1; // 没有找到匹配的闭合括号
}
}
public partial class CardDescriptionInterpreter
{
private static string GetDynamicValue(float current, float baseValue, bool normalMode)
{
string color;
if (current > baseValue)
color = normalMode ? "green" : "red";
else if (current < baseValue)
color = normalMode ? "red" : "green";
else
color = "white";
//Debug.Log($"GetDynamicValue: current={current}, baseValue={baseValue}, normalMode={normalMode}, color={color}");
return $"<color={color}>{current}</color>";
}
private static string GetDynamicValue(float current)
{
return current.ToString(CultureInfo.CurrentCulture);
}
private static string Keyword(string keyword)
{
string color = "orange";
return $"<color={color}>{keyword}</color>";
}
private static string RemoveWhenSelecting(CardLogicBase card, string toRemove)
{
return card.handCardView != null && card.handCardView.isSelecting ? "" : toRemove;
}
private static string AttributeCheck(string attributeName, float requirement, float probability)
{
if (probability < 0)
{
return "{" + attributeName + " check: " + requirement + "}";
}
int percent = Mathf.RoundToInt(probability * 100);
string result = percent + "%";
if (percent == 0)
{
result = "<color=red>" + result + "</color>";
}
else if (percent > 0 && percent < 100)
{
result = "<color=yellow>" + result + "</color>";
}
else if (percent == 100)
{
result = "<color=green>" + result + "</color>";
}
return result;
}
}
}