Files
WulaFallenEmpireRW/Source/WulaFallenEmpire/EventSystem/QuestNode/QuestNode_WriteToEventVariablesWithAdd.cs
ProjectKoi-Kalo\Kalo 98a0400c78 WulaFallenEmpireSettings.cs - 添加了 public bool enableDebugLogs = false; 字段和保存配置
 WulaLog.cs - 修改了DebugEnabled属性,仅检查enableDebugLogs设置(不检查DevMode)
 WulaFallenEmpireMod.cs - 在DoSettingsWindowContents中添加了UI复选框,显示"Enable Debug Logs"选项
 替换了所有848个Log.Message/Error/Warning调用为WulaLog.Debug()
2025-12-15 13:05:50 +08:00

537 lines
19 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 RimWorld.QuestGen;
using Verse;
using System.Collections.Generic;
using System.Linq;
namespace WulaFallenEmpire
{
public class QuestNode_WriteToEventVariablesWithAdd : QuestNode
{
// 要写入的变量名在EventVariableManager中的名字
[NoTranslate]
public SlateRef<string> targetVariableName;
// 要从Quest中读取的变量名Slate中的变量
[NoTranslate]
public SlateRef<string> sourceVariableName;
// 如果sourceVariableName为空使用这个值
public SlateRef<object> value;
// 写入模式
public WriteMode writeMode = WriteMode.Set;
// 是否检查变量已存在
public SlateRef<bool> checkExisting = true;
// 如果变量已存在是否覆盖仅用于Set模式
public SlateRef<bool> overwrite = false;
// 操作符用于Add和Multiply模式
public MathOperator mathOperator = MathOperator.Add;
// 是否强制转换类型(当类型不匹配时)
public SlateRef<bool> forceTypeConversion = false;
// 当类型不匹配且无法转换时的行为
public TypeMismatchBehavior onTypeMismatch = TypeMismatchBehavior.ConvertToString;
// 写入后是否从Slate中删除源变量
public SlateRef<bool> removeFromSlate = false;
// 是否记录调试信息
public SlateRef<bool> logDebug = false;
// 允许操作的数值类型
public List<Type> allowedNumericTypes = new List<Type>
{
typeof(int),
typeof(float),
typeof(double),
typeof(long),
typeof(short),
typeof(decimal)
};
public enum WriteMode
{
Set, // 直接设置值(覆盖)
Add, // 相加(仅对数值类型)
Multiply, // 相乘(仅对数值类型)
Append, // 追加(字符串、列表等)
Min, // 取最小值(仅对数值类型)
Max, // 取最大值(仅对数值类型)
Increment // 自增1仅对数值类型忽略源值
}
public enum MathOperator
{
Add, // 加法
Subtract, // 减法
Multiply, // 乘法
Divide // 除法
}
public enum TypeMismatchBehavior
{
ThrowError, // 抛出错误
Skip, // 跳过操作
ConvertToString,// 转换为字符串
UseDefault // 使用默认值
}
protected override bool TestRunInt(Slate slate)
{
return RunInternal(slate, isTestRun: true);
}
protected override void RunInt()
{
RunInternal(QuestGen.slate, isTestRun: false);
}
private bool RunInternal(Slate slate, bool isTestRun)
{
// 获取目标变量名
string targetName = targetVariableName.GetValue(slate);
if (string.IsNullOrEmpty(targetName))
{
WulaLog.Debug("[QuestNode_WriteToEventVariablesWithAdd] targetVariableName is null or empty!");
return false;
}
// 获取要操作的值
object sourceValue = GetSourceValue(slate);
if (sourceValue == null && writeMode != WriteMode.Increment)
{
if (logDebug.GetValue(slate))
{
WulaLog.Debug($"[QuestNode_WriteToEventVariablesWithAdd] No value to operate for variable '{targetName}'.");
}
return false;
}
// 在测试运行时不需要实际写入
if (isTestRun)
{
return true;
}
// 获取EventVariableManager
var eventVarManager = Find.World.GetComponent<EventVariableManager>();
if (eventVarManager == null)
{
WulaLog.Debug("[QuestNode_WriteToEventVariablesWithAdd] EventVariableManager not found!");
return false;
}
bool variableExists = eventVarManager.HasVariable(targetName);
object currentValue = variableExists ? eventVarManager.GetVariable<object>(targetName) : null;
// 记录操作前的状态
if (logDebug.GetValue(slate))
{
WulaLog.Debug($"[QuestNode_WriteToEventVariablesWithAdd] Operation for variable '{targetName}':");
WulaLog.Debug($" - Mode: {writeMode}");
WulaLog.Debug($" - Current value: {currentValue ?? "[null]"} (Type: {currentValue?.GetType().Name ?? "null"})");
WulaLog.Debug($" - Source value: {sourceValue ?? "[null]"} (Type: {sourceValue?.GetType().Name ?? "null"})");
}
// 根据写入模式计算新值
object newValue = CalculateNewValue(currentValue, sourceValue, slate);
// 如果新值为null可能是由于类型不匹配被跳过了
if (newValue == null)
{
if (logDebug.GetValue(slate))
{
WulaLog.Debug($" - Operation skipped (new value is null)");
}
return false;
}
// 写入变量
eventVarManager.SetVariable(targetName, newValue);
// 写入后从Slate中删除源变量
if (removeFromSlate.GetValue(slate) && !string.IsNullOrEmpty(sourceVariableName.GetValue(slate)))
{
slate.Remove(sourceVariableName.GetValue(slate));
if (logDebug.GetValue(slate))
{
WulaLog.Debug($" - Removed source variable '{sourceVariableName.GetValue(slate)}' from Slate");
}
}
// 验证写入
if (logDebug.GetValue(slate))
{
object readBackValue = eventVarManager.GetVariable<object>(targetName);
bool writeVerified = (readBackValue == null && newValue == null) ||
(readBackValue != null && readBackValue.Equals(newValue));
WulaLog.Debug($" - New value written: {newValue} (Type: {newValue.GetType().Name})");
WulaLog.Debug($" - Write verified: {writeVerified}");
if (!writeVerified)
{
WulaLog.Debug($" - Verification failed! Expected: {newValue}, Got: {readBackValue}");
}
}
return true;
}
private object GetSourceValue(Slate slate)
{
string sourceName = sourceVariableName.GetValue(slate);
if (!string.IsNullOrEmpty(sourceName))
{
if (slate.TryGet<object>(sourceName, out var slateValue))
{
return slateValue;
}
}
return value.GetValue(slate);
}
private object CalculateNewValue(object currentValue, object sourceValue, Slate slate)
{
switch (writeMode)
{
case WriteMode.Set:
return HandleSetMode(currentValue, sourceValue, slate);
case WriteMode.Add:
case WriteMode.Multiply:
return HandleMathOperation(currentValue, sourceValue, writeMode == WriteMode.Add, slate);
case WriteMode.Append:
return HandleAppendMode(currentValue, sourceValue, slate);
case WriteMode.Min:
return HandleMinMaxMode(currentValue, sourceValue, isMin: true, slate);
case WriteMode.Max:
return HandleMinMaxMode(currentValue, sourceValue, isMin: false, slate);
case WriteMode.Increment:
return HandleIncrementMode(currentValue, slate);
default:
return sourceValue;
}
}
private object HandleSetMode(object currentValue, object sourceValue, Slate slate)
{
bool variableExists = currentValue != null;
if (checkExisting.GetValue(slate) && variableExists)
{
if (!overwrite.GetValue(slate))
{
if (logDebug.GetValue(slate))
{
WulaLog.Debug($" - Variable exists and overwrite is false, keeping current value");
}
return currentValue; // 不覆盖,返回原值
}
}
return sourceValue;
}
private object HandleMathOperation(object currentValue, object sourceValue, bool isAddition, Slate slate)
{
// 如果当前值不存在,直接使用源值
if (currentValue == null)
{
return sourceValue;
}
// 尝试进行数学运算
try
{
// 检查类型是否支持数学运算
if (!IsNumericType(currentValue.GetType()) || !IsNumericType(sourceValue.GetType()))
{
return HandleTypeMismatch(currentValue, sourceValue, "non-numeric", slate);
}
// 转换为动态类型以进行数学运算
dynamic current = ConvertToBestNumericType(currentValue);
dynamic source = ConvertToBestNumericType(sourceValue);
dynamic result;
switch (mathOperator)
{
case MathOperator.Add:
result = current + source;
break;
case MathOperator.Subtract:
result = current - source;
break;
case MathOperator.Multiply:
result = current * source;
break;
case MathOperator.Divide:
if (source == 0)
{
WulaLog.Debug($"[QuestNode_WriteToEventVariablesWithAdd] Division by zero for variable operation");
return currentValue;
}
result = current / source;
break;
default:
result = current + source;
break;
}
// 根据配置决定返回类型
if (forceTypeConversion.GetValue(slate))
{
// 转换为与当前值相同的类型
return Convert.ChangeType(result, currentValue.GetType());
}
else
{
// 返回最佳类型通常是double或decimal
return result;
}
}
catch (Exception ex)
{
if (logDebug.GetValue(slate))
{
WulaLog.Debug($"[QuestNode_WriteToEventVariablesWithAdd] Math operation failed: {ex.Message}");
}
return currentValue;
}
}
private object HandleAppendMode(object currentValue, object sourceValue, Slate slate)
{
// 如果当前值不存在,直接使用源值
if (currentValue == null)
{
return sourceValue;
}
// 处理字符串追加
if (currentValue is string currentStr && sourceValue is string sourceStr)
{
return currentStr + sourceStr;
}
// 处理列表追加
if (currentValue is System.Collections.IEnumerable currentEnumerable &&
sourceValue is System.Collections.IEnumerable sourceEnumerable)
{
try
{
// 尝试创建新列表并添加所有元素
var resultList = new List<object>();
foreach (var item in currentEnumerable)
resultList.Add(item);
foreach (var item in sourceEnumerable)
resultList.Add(item);
return resultList;
}
catch
{
// 如果列表操作失败,回退到字符串追加
return currentValue.ToString() + sourceValue.ToString();
}
}
// 其他类型:转换为字符串并追加
return currentValue.ToString() + sourceValue.ToString();
}
private object HandleMinMaxMode(object currentValue, object sourceValue, bool isMin, Slate slate)
{
// 如果当前值不存在,直接使用源值
if (currentValue == null)
{
return sourceValue;
}
// 检查类型是否支持比较
if (!(currentValue is IComparable currentComparable) || !(sourceValue is IComparable sourceComparable))
{
return HandleTypeMismatch(currentValue, sourceValue, "non-comparable", slate);
}
try
{
int comparison = currentComparable.CompareTo(sourceComparable);
if (isMin)
{
// 取最小值
return comparison <= 0 ? currentValue : sourceValue;
}
else
{
// 取最大值
return comparison >= 0 ? currentValue : sourceValue;
}
}
catch (ArgumentException)
{
// 类型不匹配,无法比较
return HandleTypeMismatch(currentValue, sourceValue, "type mismatch for comparison", slate);
}
}
private object HandleIncrementMode(object currentValue, Slate slate)
{
// 如果当前值不存在从1开始
if (currentValue == null)
{
return 1;
}
// 检查是否是数值类型
if (!IsNumericType(currentValue.GetType()))
{
if (logDebug.GetValue(slate))
{
WulaLog.Debug($"[QuestNode_WriteToEventVariablesWithAdd] Cannot increment non-numeric type: {currentValue.GetType().Name}");
}
return currentValue;
}
try
{
dynamic current = ConvertToBestNumericType(currentValue);
dynamic result = current + 1;
if (forceTypeConversion.GetValue(slate))
{
return Convert.ChangeType(result, currentValue.GetType());
}
else
{
return result;
}
}
catch (Exception ex)
{
if (logDebug.GetValue(slate))
{
WulaLog.Debug($"[QuestNode_WriteToEventVariablesWithAdd] Increment operation failed: {ex.Message}");
}
return currentValue;
}
}
private object HandleTypeMismatch(object currentValue, object sourceValue, string mismatchReason, Slate slate)
{
if (logDebug.GetValue(slate))
{
WulaLog.Debug($"[QuestNode_WriteToEventVariablesWithAdd] Type mismatch for operation: {mismatchReason}");
}
switch (onTypeMismatch)
{
case TypeMismatchBehavior.ThrowError:
throw new InvalidOperationException($"Type mismatch for operation: {mismatchReason}");
case TypeMismatchBehavior.Skip:
if (logDebug.GetValue(slate))
{
WulaLog.Debug($" - Skipping operation due to type mismatch");
}
return currentValue; // 保持原值
case TypeMismatchBehavior.ConvertToString:
// 都转换为字符串
return currentValue.ToString() + " | " + sourceValue.ToString();
case TypeMismatchBehavior.UseDefault:
// 使用源值作为默认
return sourceValue;
default:
return currentValue;
}
}
private bool IsNumericType(Type type)
{
if (type == null) return false;
TypeCode typeCode = Type.GetTypeCode(type);
switch (typeCode)
{
case TypeCode.Byte:
case TypeCode.SByte:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Single:
return true;
default:
return false;
}
}
private dynamic ConvertToBestNumericType(object value)
{
if (value == null) return 0;
Type type = value.GetType();
TypeCode typeCode = Type.GetTypeCode(type);
switch (typeCode)
{
case TypeCode.Decimal:
return (decimal)value;
case TypeCode.Double:
return (double)value;
case TypeCode.Single:
return (float)value;
case TypeCode.Int64:
return (long)value;
case TypeCode.Int32:
return (int)value;
case TypeCode.Int16:
return (short)value;
case TypeCode.UInt64:
return (ulong)value;
case TypeCode.UInt32:
return (uint)value;
case TypeCode.UInt16:
return (ushort)value;
case TypeCode.Byte:
return (byte)value;
case TypeCode.SByte:
return (sbyte)value;
default:
// 尝试转换
try
{
return Convert.ToDouble(value);
}
catch
{
return 0;
}
}
}
}
}