This commit is contained in:
SoulliesOfficial
2025-10-23 00:49:44 -04:00
parent 9b1b5ca93f
commit 61a397dd4c
9846 changed files with 2618439 additions and 793547 deletions

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic;
using Sirenix.OdinInspector;
using NaughtyAttributes;
using SLSFramework.General;
using Unity.VisualScripting;
using UnityEngine;
@@ -10,13 +11,11 @@ namespace Continentis.MainGame
/// <summary>
/// 基础属性,不会改变,通常情况下不会直接使用
/// </summary>
[DictionaryDrawerSettings(KeyColumnWidth = 400)]
public Dictionary<string, float> original;
/// <summary>
/// 当前属性会受到buff和其他效果的影响
/// </summary>
[DictionaryDrawerSettings(KeyColumnWidth = 400)]
public Dictionary<string, float> current;
public AttributeGroup(Dictionary<string, float> original)

View File

@@ -1,28 +1,45 @@
using System.Collections.Generic;
using Continentis.MainGame.Card;
using Continentis.MainGame.Character;
using DamageNumbersPro;
using Sirenix.OdinInspector;
using SLSFramework.General;
using UnityEngine;
namespace Continentis.MainGame
{
[CreateAssetMenu(menuName = "Continentis/MainGame/BasePrefabs", fileName = "MainGameBasePrefabs")]
public partial class BasePrefabs : SerializedScriptableObject
public enum Rarity
{
[Title("Character")]
None = 0,
Common = 10,
Uncommon = 20,
Rare = 30,
Epic = 40,
Legendary = 50,
Divine = 60
}
[CreateAssetMenu(menuName = "Continentis/MainGame/BasePrefabs", fileName = "MainGameBasePrefabs")]
public partial class BasePrefabs : ScriptableObject
{
[Header("Character")]
public GameObject combatCharacterView;
[Title("Cards")]
[Header("Cards")]
public GameObject handCardObject;
public GameObject intentionCardObject;
public GameObject inspectionCardObject;
public SerializableDictionary<string, CardViewCollection> cardViewCollections;
[Title("GeneralUI")]
[Header("GeneralUI")]
public GameObject informationBox;
public SerializableDictionary<Fraction, List<Sprite>> fractionFrames;
public SerializableDictionary<Rarity, Color> rarityColors;
[Title("CombatUI")]
[Header("CombatUI")]
public GameObject pointerArrow;
public GameObject hudContainer;
[Title("Texts")]
[Header("Texts")]
public GameObject hurtDamageNumber;
public GameObject blockedDamageNumber;
public GameObject healNumber;
@@ -31,6 +48,31 @@ namespace Continentis.MainGame
public partial class BasePrefabs
{
public Color GetRarityColor(Rarity rarity)
{
if (rarityColors.TryGetValue(rarity, out Color color))
{
return color;
}
return Color.white;
}
}
public partial class BasePrefabs
{
public DamageNumber GenerateHurtText(int amount, CombatCharacterViewBase characterView)
{
Vector3 position = characterView.transform.position + Vector3.up * 0.5f;
if (characterView.numbersPivot != null)
{
position = characterView.numbersPivot.position;
}
DamageNumber infoText = GenerateHurtText(amount, position);
return infoText;
}
public DamageNumber GenerateHurtText(int amount, Vector3 position)
{
DamageNumber hurtText = GenerateCombatText(hurtDamageNumber, position);
@@ -38,6 +80,19 @@ namespace Continentis.MainGame
return hurtText;
}
public DamageNumber GenerateBlockedText(int amount, CombatCharacterViewBase characterView)
{
Vector3 position = characterView.transform.position + Vector3.up * 0.5f;
if (characterView.numbersPivot != null)
{
position = characterView.numbersPivot.position;
}
DamageNumber infoText = GenerateBlockedText(amount, position);
return infoText;
}
public DamageNumber GenerateBlockedText(int amount, Vector3 position)
{
DamageNumber blockedText = GenerateCombatText(blockedDamageNumber, position);
@@ -45,6 +100,19 @@ namespace Continentis.MainGame
return blockedText;
}
public DamageNumber GenerateHealText(int amount, CombatCharacterViewBase characterView)
{
Vector3 position = characterView.transform.position + Vector3.up * 0.5f;
if (characterView.numbersPivot != null)
{
position = characterView.numbersPivot.position;
}
DamageNumber infoText = GenerateHealText(amount, position);
return infoText;
}
public DamageNumber GenerateHealText(int amount, Vector3 position)
{
DamageNumber healText = GenerateCombatText(healNumber, position);
@@ -52,6 +120,20 @@ namespace Continentis.MainGame
return healText;
}
public DamageNumber GenerateInfoText(string content, CombatCharacterViewBase characterView, Color color = default, float size = 1)
{
Vector3 position = characterView.transform.position + Vector3.up;
if (characterView.textsPivot != null)
{
position = characterView.textsPivot.position;
}
DamageNumber infoText = GenerateCombatText(informationText, position, color, size);
infoText.leftText = content;
return infoText;
}
public DamageNumber GenerateInfoText(string content, Vector3 position, Color color = default, float size = 1)
{
DamageNumber infoText = GenerateCombatText(informationText, position, color, size);

View File

@@ -1,121 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Continentis.MainGame
{
public enum BuffDispelLevel
{
Basic = 0, //弱驱散
Strong = 10, //强驱散
Immune = 20, //不可驱散(死亡除外)
Undispellable = 100 //不可驱散(包括死亡)
}
public enum BuffType
{
Positive,
Negative,
Neutral
}
public abstract partial class BuffBase<T>
{
public string name;
public string description;
public BuffType buffType;
public BuffDispelLevel dispelThreshold;
protected virtual void Initialize(string name, string description, BuffType buffType, BuffDispelLevel dispelThreshold)
{
this.name = name;
this.description = description;
this.buffType = buffType;
this.dispelThreshold = dispelThreshold;
}
}
public partial class BuffBase<T>
{
protected bool FindExistingBuff<T1, T2>(out T2 existingBuff, List<T1> buffList) where T1 : BuffBase<T> where T2 : BuffBase<T>
{
existingBuff = null;
foreach (T1 buff in buffList.Where(buff => buff.GetType() == typeof(T2)))
{
existingBuff = buff as T2;
return true;
}
return false;
}
public abstract void Apply(T attached);
public abstract void Remove();
public abstract void UntriggerRemove();
public virtual void Dispel(BuffDispelLevel dispelLevel)
{
if (CanBeDispelled(dispelLevel))
{
OnBuffDispel();
Remove();
}
}
}
public partial class BuffBase<T>
{
//Buff生命周期函数
/// <summary>
/// Buff被尝试添加到角色时调用。
/// </summary>
public virtual bool OnBuffApply(out BuffBase<T> existingBuff)
{
throw new System.NotImplementedException(); //需要在子类中实现
}
/// <summary>
/// Buff首次成功添加到角色后调用。在OnBuffApply完成且返回true之后调用。
/// 如果Buff在被添加时发现已有同类Buff存在则不会调用此函数。
/// </summary>
public virtual void OnAfterFirstApply()
{
}
/// <summary>
/// Buff被驱散移除时调用在OnBuffRemove之前调用。
/// </summary>
public virtual void OnBuffDispel()
{
}
/// <summary>
/// Buff被正常移除时调用。在Buff生命周期结束时调用。
/// UntriggerRemove不会调用此函数。但是此函数通常情况下绝不会被调用。
/// </summary>
public virtual void OnBuffRemove()
{
}
}
public partial class BuffBase<T>
{
/// <summary>
/// 判断该Buff能否被指定驱散等级的驱散效果驱散。
/// </summary>
protected bool CanBeDispelled(BuffDispelLevel dispelLevel)
{
return dispelLevel >= dispelThreshold;
}
}
}

View File

@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 9f2945f2bcd61ff499033e790f23a32b

View File

@@ -1,267 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Continentis.MainGame.UI;
using SoulliesFramework.General;
using UnityEngine;
using UnityEngine.Events;
namespace Continentis.MainGame
{
public partial class BuffBase<T>
{
public abstract class BuffSubmodule : SubmoduleBase<BuffBase<T>>
{
public BuffBase<T> buff;
protected BuffSubmodule(BuffBase<T> buff) : base(buff)
{
this.buff = buff;
}
}
public class UISubmodule : BuffSubmodule
{
public bool hasIcon;
public string iconPath;
public Sprite icon;
public List<Func<string>> setTextFunctions;
public HUD_CharacterBuffIcon buffIcon;
public UISubmodule(BuffBase<T> buff, string iconPath = "",
params Func<string>[] setTextFunctions) : base(buff)
{
this.hasIcon = !string.IsNullOrEmpty(iconPath);
this.iconPath = iconPath;
if (hasIcon)
{
this.icon = AssetLoader.LoadAsset<Sprite>(iconPath);
}
this.setTextFunctions = setTextFunctions.ToList();
}
}
public class CountSubmodule : BuffSubmodule
{
public int maximumCount;
public int remainingCount;
public bool isInfinite => maximumCount < 0;
public float remainingPercentage => (float)remainingCount / maximumCount;
/// <summary>
/// duration为负数表示无限持续时间。
/// </summary>
public CountSubmodule(BuffBase<T> buff, int maximumCount) : base(buff)
{
this.maximumCount = maximumCount;
this.remainingCount = maximumCount;
}
public void UpdateModule()
{
if (isInfinite)
{
return;
}
remainingCount--;
if (remainingCount <= 0)
{
buff.Remove();
}
}
/// <summary>
/// 刷新剩余时间至初始值。
/// </summary>
public void RefreshDuration()
{
if (isInfinite)
{
return;
}
remainingCount = maximumCount;
}
/// <summary>
/// 覆盖可选保留更大的duration并刷新剩余时间。
/// </summary>
public void RefreshDuration(int overrideDuration, bool keepMaximal = true)
{
if (isInfinite)
{
return;
}
maximumCount = keepMaximal ? Mathf.Max(maximumCount, overrideDuration) : overrideDuration;
remainingCount = maximumCount;
}
/// <summary>
/// 增加持续时间和剩余时间。
/// </summary>
public void AddDuration(int additionalDuration)
{
if (isInfinite)
{
return;
}
maximumCount += additionalDuration;
remainingCount += additionalDuration;
}
/// <summary>
/// 仅增加剩余时间,不改变总持续时间。
/// 如果增加后剩余时间超过总持续时间,则剩余时间等于总持续时间。
/// </summary>
public void AddTime(int additionalTime)
{
if (isInfinite)
{
return;
}
remainingCount += additionalTime;
remainingCount = Mathf.Min(remainingCount, maximumCount);
}
}
/// <summary>
/// Buff叠加模块叠加层数统一。
/// </summary>
public class UnitedStackSubmodule : BuffSubmodule
{
public bool willRemoveOnZero; //是否在层数为0时移除Buff
public int stackAmount; //当前层数
public int stackUpperLimit; //层数上限,-1表示无限制
public UnitedStackSubmodule(BuffBase<T> buff, bool willRemoveOnZero,
int stackUpperLimit = -1, int initialStackAmount = 1) : base(buff)
{
this.willRemoveOnZero = willRemoveOnZero;
this.stackAmount = initialStackAmount;
this.stackUpperLimit = stackUpperLimit;
}
public void RefreshStackUpperLimit(int upperLimit, bool keepMaximal = true)
{
stackUpperLimit = keepMaximal ? Mathf.Max(stackUpperLimit, upperLimit) : upperLimit;
}
public void AddStack(int amount)
{
stackAmount += amount;
if (stackUpperLimit > 0)
{
stackAmount = Mathf.Min(stackAmount, stackUpperLimit);
}
}
public void ReduceStack(int amount)
{
stackAmount -= amount;
if (willRemoveOnZero && stackAmount <= 0)
{
buff.Remove();
}
}
}
/// <summary>
/// Buff独立叠加模块每一层的持续时间和层数可以不同。
/// </summary>
public class IndependentStackSubmodule : BuffSubmodule
{
public bool willRemoveOnZero;
public List<IndependentStackUnit> independentStacks;
public int totalStackAmount;
public IndependentStackSubmodule(BuffBase<T> buff, bool willRemoveOnZero) : base(buff)
{
this.willRemoveOnZero = willRemoveOnZero;
independentStacks = new List<IndependentStackUnit>();
totalStackAmount = 0;
}
public void UpdateModule()
{
independentStacks.ForEach(x => x.remainingTime--);
independentStacks.RemoveAll(x => !x.IsInfinite && x.remainingTime <= 0);
totalStackAmount = independentStacks.Sum(x => x.stackAmount);
if (willRemoveOnZero && totalStackAmount <= 0)
{
buff.Remove();
}
}
public IndependentStackUnit AddStack(int stackAmount, int duration)
{
IndependentStackUnit addition = new IndependentStackUnit(stackAmount, duration);
independentStacks.Add(addition);
independentStacks.Sort();
return addition;
}
public void ReduceStack(int stackAmount)
{
for (int i = 0; i < independentStacks.Count; i++)
{
if (stackAmount <= independentStacks[i].stackAmount)
{
independentStacks[i].stackAmount -= stackAmount;
if (independentStacks[i].stackAmount <= 0)
{
independentStacks.RemoveAt(i);
}
return;
}
stackAmount -= independentStacks[i].stackAmount;
independentStacks.RemoveAt(i);
i--;
}
totalStackAmount = independentStacks.Sum(x => x.stackAmount);
if (willRemoveOnZero && totalStackAmount <= 0)
{
buff.Remove();
}
}
public class IndependentStackUnit : IComparable<IndependentStackUnit>
{
public int stackAmount;
public int duration;
public int remainingTime;
public Dictionary<string, float> parameters;
public bool IsInfinite => duration < 0;
public IndependentStackUnit(int stackAmount, int duration)
{
this.stackAmount = stackAmount;
this.duration = duration;
this.remainingTime = duration;
this.parameters = new Dictionary<string, float>();
}
public int CompareTo(IndependentStackUnit other)
{
return remainingTime.CompareTo(other.remainingTime);
}
}
}
}
}

View File

@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 27fbd8e42b698e54281f2ac2c22f4993

View File

@@ -1,59 +0,0 @@
using SoulliesFramework.General;
using UnityEngine;
using UnityEngine.Events;
namespace Continentis.MainGame
{
public class EventUnit : IPrioritized
{
private UnityAction action;
public int Priority { get; set; }
public EventUnit(UnityAction action, int priority = 0)
{
this.action = action;
this.Priority = priority;
}
public void Invoke()
{
action.Invoke();
}
}
public class EventUnit<T> : IPrioritized
{
private UnityAction<T> action;
public int Priority { get; set; }
public EventUnit(UnityAction<T> action, int priority = 0)
{
this.action = action;
this.Priority = priority;
}
public void Invoke(T arg)
{
action.Invoke(arg);
}
}
public class EventUnit<T1, T2> : IPrioritized
{
private UnityAction<T1, T2> action;
public int Priority { get; set; }
public EventUnit(UnityAction<T1, T2> action, int priority = 0)
{
this.action = action;
this.Priority = priority;
}
public void Invoke(T1 arg1, T2 arg2)
{
action.Invoke(arg1, arg2);
}
}
}

View File

@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: d4a739f10fb7d8d49a75be3de4f95ac8

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 8f16a5fe2cd8e2741b4791152560326b
guid: 5bc79878df4668d44bfbd60ff14a5741
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using DynamicExpresso;
using UnityEngine;
namespace Continentis.MainGame
{
public static partial class BuffTextInterpreter
{
private static readonly Interpreter TextInterpreter;
static BuffTextInterpreter()
{
TextInterpreter = new Interpreter();
TextInterpreter.SetFunction("Value", new Func<float, string>((cv) => DynamicTextInterpreter.GetValue(cv, false)));
TextInterpreter.SetFunction("Value", new Func<float, float, string>((cv, bv) => DynamicTextInterpreter.GetValue(cv, bv, true, false)));
TextInterpreter.SetFunction("Value",
new Func<float, float, bool, string>((cv, bv, high) => DynamicTextInterpreter.GetValue(cv, bv, high, false)));
TextInterpreter.SetFunction("Value",
new Func<float, float, bool, bool, string>((cv, bv, high, percent) => DynamicTextInterpreter.GetValue(cv, bv, high, percent)));
foreach (KeyValuePair<string, InterpretedKeyword> keyword in MainGameManager.Instance.keywordData.interpretedKeywords)
{
TextInterpreter.SetVariable(keyword.Key, keyword.Key);
}
}
public static void InterpretText<T>(BuffBase<T> buff)
{
TextInterpreter.SetFunction("ParameterInt", new Func<string, string>((paramName) => GetParameterInt(buff, paramName, false)));
TextInterpreter.SetFunction("ParameterAbsInt", new Func<string, string>((paramName) => GetParameterInt(buff, paramName, true)));
TextInterpreter.SetFunction("ParameterPercent", new Func<string, string>((paramName) => GetParameterPercent(buff, paramName)));
TextInterpreter.SetFunction("ParameterFloat", new Func<string, string>((paramName) => GetParameterFloat(buff, paramName)));
TextInterpreter.SetFunction("ParameterString", new Func<string, string>((paramName) => GetParameterString(buff, paramName)));
string descriptionToParse = buff.contentSubmodule.originalFunctionText;
string result = DynamicTextInterpreter.Parse(TextInterpreter, descriptionToParse, new List<string>(), new List<string>());
buff.contentSubmodule.interpretedFunctionText = result;
}
}
public static partial class BuffTextInterpreter
{
private static string GetParameterInt<T>(BuffBase<T> buff, string parameterName, bool isAbsolute)
{
if (buff.contentSubmodule.parameterGetters.TryGetValue(parameterName, out Func<string> getter))
{
int intValue = Convert.ToInt32(getter());
if (isAbsolute)
{
return Math.Abs(intValue).ToString();
}
else
{
return intValue.ToString();
}
}
Debug.LogError($"无法找到参数获取器: {parameterName} 在 Buff: {buff.contentSubmodule.displayName}");
return "ERROR";
}
private static string GetParameterFloat<T>(BuffBase<T> buff, string parameterName)
{
if (buff.contentSubmodule.parameterGetters.TryGetValue(parameterName, out Func<string> getter))
{
return Convert.ToSingle(getter()).ToString(CultureInfo.InvariantCulture);
}
Debug.LogError($"无法找到参数获取器: {parameterName} 在 Buff: {buff.contentSubmodule.displayName}");
return "ERROR";
}
private static string GetParameterPercent<T>(BuffBase<T> buff, string parameterName)
{
if (buff.contentSubmodule.parameterGetters.TryGetValue(parameterName, out Func<string> getter))
{
return Mathf.RoundToInt(Convert.ToSingle(getter()) * 100).ToString() + "%";
}
Debug.LogError($"无法找到参数获取器: {parameterName} 在 Buff: {buff.contentSubmodule.displayName}");
return "ERROR";
}
private static string GetParameterString<T>(BuffBase<T> buff, string parameterName)
{
if (buff.contentSubmodule.parameterGetters.TryGetValue(parameterName, out Func<string> getter))
{
return getter();
}
Debug.LogError($"无法找到参数获取器: {parameterName} 在 Buff: {buff.contentSubmodule.displayName}");
return "ERROR";
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f764ba86ad36ace4f97961d6765b6710

View File

@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using Continentis.MainGame.Card;
using DynamicExpresso;
using UnityEngine;
namespace Continentis.MainGame
{
public static partial class CardTextInterpreter
{
private static readonly Interpreter TextInterpreter;
static CardTextInterpreter()
{
TextInterpreter = new Interpreter();
TextInterpreter.SetFunction("Value", new Func<float, string>((cv) => DynamicTextInterpreter.GetValue(cv, false)));
TextInterpreter.SetFunction("Value", new Func<float, float, string>((cv, bv) => DynamicTextInterpreter.GetValue(cv, bv, true, false)));
TextInterpreter.SetFunction("Value", new Func<float, float, bool, string>((cv, bv, high) => DynamicTextInterpreter.GetValue(cv, bv, high, false)));
TextInterpreter.SetFunction("Value", new Func<float, float, bool, bool, string>((cv, bv, high, percent) => DynamicTextInterpreter.GetValue(cv, bv, high, percent)));
foreach (KeyValuePair<string, InterpretedKeyword> keyword in MainGameManager.Instance.keywordData.interpretedKeywords)
{
TextInterpreter.SetVariable(keyword.Key, keyword.Key);
}
}
public static void InterpretText(CardLogicBase card, bool overrideDescription = false)
{
card.contentSubmodule.keywords.Clear();
foreach (KeyValuePair<string, float> attribute in card.attributeSubmodule.attributeGroup.current)
{
TextInterpreter.SetVariable(attribute.Key, attribute.Value);
}
TextInterpreter.SetFunction("RemoveWhenSelecting", new Func<string, string>((toRemove) => RemoveWhenSelecting(card, toRemove)));
TextInterpreter.SetFunction("Attribute", new Func<string, string>((name) => GetAttribute(card, name, true, false)));
TextInterpreter.SetFunction("Attribute", new Func<string, bool, string>((name, high) => GetAttribute(card, name, high, false)));
TextInterpreter.SetFunction("Attribute", new Func<string, bool, bool, string>((name, high, percent) => GetAttribute(card, name, high, percent)));
string descriptionToParse = card.contentSubmodule.originalFunctionText;
string result = DynamicTextInterpreter.Parse(TextInterpreter, descriptionToParse, card.contentSubmodule.keywords, card.contentSubmodule.hintKeywords);
card.contentSubmodule.interpretedFunctionText = result;
Debug.Log($"Interpreted Description: {result}");
}
}
public static partial class CardTextInterpreter
{
private static string GetAttribute(CardLogicBase card, string attributeName, bool higherIsBetter, bool inPercent)
{
string displayName = "Display" + attributeName;
string baseName = "Base" + attributeName;
string baseOffsetName = "Base" + attributeName + "Offset";
if (!inPercent)
{
int displayValue = card.GetAttribute(displayName);
int baseValue = card.GetAttribute(baseName) + card.GetAttribute(baseOffsetName);
return DynamicTextInterpreter.GetValue(displayValue, baseValue, higherIsBetter, false);
}
else
{
float rawDisplayValue = card.GetRawAttribute(displayName);
float rawBaseValue = card.GetRawAttribute(baseName) + card.GetRawAttribute(baseOffsetName);
return DynamicTextInterpreter.GetValue(rawDisplayValue, rawBaseValue, higherIsBetter, true);
}
}
private static string GetAttribute(CardLogicBase card, string attributeName, bool inPercent)
{
string displayName = "Display" + attributeName;
int displayValue = card.GetAttribute(displayName);
return DynamicTextInterpreter.GetValue(displayValue, inPercent);
}
private static string RemoveWhenSelecting(CardLogicBase card, string toRemove)
{
return card.handCardView != null && card.handCardView.isSelecting ? "" : toRemove;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ef10462731b5127408af93915f8671e9

View File

@@ -0,0 +1,167 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using Continentis.MainGame.Card;
using DynamicExpresso;
using SLSFramework.General;
using UnityEngine;
namespace Continentis.MainGame
{
public partial class DynamicTextInterpreter
{
public static string Parse(Interpreter interpreter, string template, List<string> keywords, List<string> hintKeywords)
{
interpreter.UnsetFunction("Keyword");
interpreter.SetFunction("Keyword", new Func<string, string>(kw => SetKeyword(ref keywords, kw)));
interpreter.UnsetFunction("HintKeyword");
interpreter.SetFunction("HintKeyword", new Func<string, string>(kw => SetKeyword(ref hintKeywords, kw)));
interpreter.UnsetFunction("DescKeyword");
interpreter.SetFunction("DescKeyword", new Func<string, string>(DescKeyword));
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 = interpreter.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;
//本地函数,用于添加关键词到集合中并返回格式化后的关键词字符串
string SetKeyword(ref List<string> collection, string keyword)
{
if (!string.IsNullOrEmpty(keyword) && !collection.Contains(keyword))
{
collection.Add(keyword);
}
return Keyword(keyword);
}
}
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 DynamicTextInterpreter
{
public static string GetValue(float currentValue, float baseValue, bool higherIsBetter, bool inPercent)
{
string color = "white";
if (currentValue > baseValue)
{
color = higherIsBetter ? "green" : "red";
}
else if (currentValue < baseValue)
{
color = higherIsBetter ? "red" : "green";
}
string valueStr = currentValue.ToString(CultureInfo.InvariantCulture);
if (inPercent)
{
valueStr = Mathf.RoundToInt(currentValue * 100) + "%";
}
return $"<color={color}>{valueStr}</color>";
}
public static string GetValue(float currentValue, bool inPercent)
{
string valueStr = currentValue.ToString(CultureInfo.InvariantCulture);
if (inPercent)
{
valueStr = Mathf.RoundToInt(currentValue * 100) + "%";
}
return valueStr;
}
public static string Keyword(string key)
{
string color = "orange";
string result = key;
if (MainGameManager.Instance.keywordData.TryGetKeyword(key, out InterpretedKeyword keyword))
{
result = keyword.name.Localize();
}
return $"<color={color}>{result}</color>";
}
public static string DescKeyword(string key)
{
string color = "yellow";
string result = key;
if (MainGameManager.Instance.keywordData.TryGetKeyword(key, out InterpretedKeyword keyword))
{
result = keyword.name.Localize();
}
return $"<color={color}>{result}</color>";
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c47182d113862b84bb5ce50653b608f1

View File

@@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using NaughtyAttributes;
using SLSFramework.General;
using UnityEngine;
namespace Continentis.MainGame
{
[CreateAssetMenu(menuName = "Continentis/KeywordData", fileName = "KeywordData")]
public partial class KeywordData : ScriptableObject
{
[Tooltip("关键词在显示上使用InterpretedKeyword的信息")]
[KeyWidth(0.2f)]
public SerializableDictionary<string, InterpretedKeyword> interpretedKeywords = new SerializableDictionary<string, InterpretedKeyword>();
/// <summary>
/// 尝试获取关键词,基础关键词和解释关键词均可
/// </summary>
public bool TryGetLocalizedKeyword(string key, out string locName, out string locDesc)
{
if (TryGetKeyword(key, out InterpretedKeyword keyword))
{
locName = keyword.name.Localize();
locDesc = keyword.description.Localize();
return true;
}
locName = keyword.name;
locDesc = keyword.description;
return false;
}
/// <summary>
/// 尝试获取关键词,基础关键词和解释关键词均可
/// </summary>
public bool TryGetKeyword(string key, out InterpretedKeyword keyword)
{
if (interpretedKeywords.TryGetValue(key, out keyword))
{
return true;
}
keyword = default;
return false;
}
}
public partial class KeywordData
{
public string keywordToAdd;
[Button]
private void AddKeywordToCollection()
{
InterpretedKeyword ik = new InterpretedKeyword("Keyword_" + keywordToAdd, "Keyword_" + keywordToAdd + "_Description");
interpretedKeywords.TryAdd(keywordToAdd, ik);
}
}
[Serializable]
public struct InterpretedKeyword
{
public string name;
public string description;
public InterpretedKeyword(string name, string description)
{
this.name = name;
this.description = description;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 3f37d7342fd3cbf4a9b837fca74655cc

View File

@@ -0,0 +1,15 @@
using System;
using SLSFramework.General;
using SLSFramework.General.LeanPoolAssistance;
using UnityEngine;
namespace Continentis.MainGame
{
public class VisualEffectBase : PooledObject
{
private void Awake()
{
//GetComponentsInChildren<Renderer>().For(rend => rend.sortingOrder = 200);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2bff3d4a9372dc6408419c254d757aac