diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll index 5f50a45c..091d6592 100644 Binary files a/1.6/1.6/Assemblies/WulaFallenEmpire.dll and b/1.6/1.6/Assemblies/WulaFallenEmpire.dll differ diff --git a/1.6/1.6/Defs/QuestScriptDefs/WULA_Base_Tex_Quest.xml b/1.6/1.6/Defs/QuestScriptDefs/WULA_Base_Tex_Quest.xml index 0677e95d..f1de6faf 100644 --- a/1.6/1.6/Defs/QuestScriptDefs/WULA_Base_Tex_Quest.xml +++ b/1.6/1.6/Defs/QuestScriptDefs/WULA_Base_Tex_Quest.xml @@ -112,6 +112,14 @@ 1 taxAmount +
  • + WULA_Total_Tax_Amount + taxAmount + 0 + Set + true +
  • +
  • Silver $taxAmount diff --git a/1.6/1.6/Defs/Scenarios/Scenarios_WULA.xml b/1.6/1.6/Defs/Scenarios/Scenarios_WULA.xml index 500c7d29..be017ed0 100644 --- a/1.6/1.6/Defs/Scenarios/Scenarios_WULA.xml +++ b/1.6/1.6/Defs/Scenarios/Scenarios_WULA.xml @@ -244,6 +244,18 @@ 1
  • + +
  • + ScatterThingsNearPlayerStart + Steel + 500 +
  • +
  • + ScatterThingsNearPlayerStart + ComponentIndustrial + 30 +
  • +
  • StartingResearch diff --git a/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Turret_Buildings.xml b/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Turret_Buildings.xml index 11c72a55..9af286df 100644 --- a/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Turret_Buildings.xml +++ b/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Turret_Buildings.xml @@ -1882,7 +1882,6 @@ None (0.56, 0.62, 0.9) Wula/Building/WULA_Combat_Excavator_Icon - WULA_Buildings false Wula/Building/WULA_Combat_Excavator @@ -2332,7 +2331,6 @@ None (0.56, 0.62, 0.9) Wula/Building/WULA_Combat_Excavator_Icon - WULA_Buildings false Wula/Building/WULA_Combat_Excavator @@ -2432,23 +2430,23 @@
  • - WULA_Combat_Excavator_Shoke_S_Damage - 5 + WULA_Sow_Excavator_Shoke_Damage + 4 2 10 Wula_Disturber_Turret_Weapon_Explosive
  • - WULA_Combat_Excavator_Shoke_S_Damage - 7 + WULA_Sow_Excavator_Shoke_Damage + 6 2 10 0.9 Wula_Disturber_Turret_Weapon_Explosive
  • - WULA_Combat_Excavator_Shoke_Damage - 7 + WULA_Sow_Excavator_Shoke_Damage + 8 2 20 0.9 diff --git a/1.6/1.6/Languages/ChineseSimplified (简体中文)/DefInjected/QuestScriptDef/WULA_Base_Tex_Quest.xml b/1.6/1.6/Languages/ChineseSimplified (简体中文)/DefInjected/QuestScriptDef/WULA_Base_Tex_Quest.xml index 45a7358b..800e3aa2 100644 --- a/1.6/1.6/Languages/ChineseSimplified (简体中文)/DefInjected/QuestScriptDef/WULA_Base_Tex_Quest.xml +++ b/1.6/1.6/Languages/ChineseSimplified (简体中文)/DefInjected/QuestScriptDef/WULA_Base_Tex_Quest.xml @@ -4,6 +4,6 @@
  • questName->什一税税收
  • -
  • questDescription->唯死亡和税收不可避免——按时上交什一税是乌拉帝国殖民地的光荣义务。\n\n乌拉帝国每隔一个季度(15天)收一次什一税,什一税会从殖民地储存在舰队中的资产里面扣除,你可以建造<color=#6BB7B7><i>乌拉帝国物资输送舱</i></color>来将物资输送到位于轨道上的舰队。\n\n乌拉帝国对积极纳税的殖民地会给予更多关照——但是如果拖延,则每延期一天都会惹其不快,最后甚至有可能被定性为叛国!
  • +
  • questDescription->唯死亡和税收不可避免——按时上交什一税是乌拉帝国殖民地的光荣义务。\n\n乌拉帝国每隔10天收一次什一税,什一税会从殖民地储存在舰队中的资产里面扣除,你可以建造<color=#6BB7B7><i>乌拉帝国物资输送舱</i></color>来将物资输送到位于轨道上的舰队。\n\n乌拉帝国对积极纳税的殖民地会给予更多关照——但是如果拖延,则每延期一天都会惹其不快,最后甚至有可能被定性为叛国!
  • \ No newline at end of file diff --git a/Source/WulaFallenEmpire/EventSystem/QuestNode/QuestNode_WriteToEventVariablesWithAdd.cs b/Source/WulaFallenEmpire/EventSystem/QuestNode/QuestNode_WriteToEventVariablesWithAdd.cs new file mode 100644 index 00000000..10a21a9b --- /dev/null +++ b/Source/WulaFallenEmpire/EventSystem/QuestNode/QuestNode_WriteToEventVariablesWithAdd.cs @@ -0,0 +1,536 @@ +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 targetVariableName; + + // 要从Quest中读取的变量名(Slate中的变量) + [NoTranslate] + public SlateRef sourceVariableName; + + // 如果sourceVariableName为空,使用这个值 + public SlateRef value; + + // 写入模式 + public WriteMode writeMode = WriteMode.Set; + + // 是否检查变量已存在 + public SlateRef checkExisting = true; + + // 如果变量已存在,是否覆盖(仅用于Set模式) + public SlateRef overwrite = false; + + // 操作符(用于Add和Multiply模式) + public MathOperator mathOperator = MathOperator.Add; + + // 是否强制转换类型(当类型不匹配时) + public SlateRef forceTypeConversion = false; + + // 当类型不匹配且无法转换时的行为 + public TypeMismatchBehavior onTypeMismatch = TypeMismatchBehavior.ConvertToString; + + // 写入后是否从Slate中删除源变量 + public SlateRef removeFromSlate = false; + + // 是否记录调试信息 + public SlateRef logDebug = false; + + // 允许操作的数值类型 + public List allowedNumericTypes = new List + { + 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)) + { + Log.Error("[QuestNode_WriteToEventVariablesWithAdd] targetVariableName is null or empty!"); + return false; + } + + // 获取要操作的值 + object sourceValue = GetSourceValue(slate); + if (sourceValue == null && writeMode != WriteMode.Increment) + { + if (logDebug.GetValue(slate)) + { + Log.Warning($"[QuestNode_WriteToEventVariablesWithAdd] No value to operate for variable '{targetName}'."); + } + return false; + } + + // 在测试运行时不需要实际写入 + if (isTestRun) + { + return true; + } + + // 获取EventVariableManager + var eventVarManager = Find.World.GetComponent(); + if (eventVarManager == null) + { + Log.Error("[QuestNode_WriteToEventVariablesWithAdd] EventVariableManager not found!"); + return false; + } + + bool variableExists = eventVarManager.HasVariable(targetName); + object currentValue = variableExists ? eventVarManager.GetVariable(targetName) : null; + + // 记录操作前的状态 + if (logDebug.GetValue(slate)) + { + Log.Message($"[QuestNode_WriteToEventVariablesWithAdd] Operation for variable '{targetName}':"); + Log.Message($" - Mode: {writeMode}"); + Log.Message($" - Current value: {currentValue ?? "[null]"} (Type: {currentValue?.GetType().Name ?? "null"})"); + Log.Message($" - Source value: {sourceValue ?? "[null]"} (Type: {sourceValue?.GetType().Name ?? "null"})"); + } + + // 根据写入模式计算新值 + object newValue = CalculateNewValue(currentValue, sourceValue, slate); + + // 如果新值为null(可能是由于类型不匹配被跳过了) + if (newValue == null) + { + if (logDebug.GetValue(slate)) + { + Log.Message($" - 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)) + { + Log.Message($" - Removed source variable '{sourceVariableName.GetValue(slate)}' from Slate"); + } + } + + // 验证写入 + if (logDebug.GetValue(slate)) + { + object readBackValue = eventVarManager.GetVariable(targetName); + bool writeVerified = (readBackValue == null && newValue == null) || + (readBackValue != null && readBackValue.Equals(newValue)); + + Log.Message($" - New value written: {newValue} (Type: {newValue.GetType().Name})"); + Log.Message($" - Write verified: {writeVerified}"); + if (!writeVerified) + { + Log.Warning($" - 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(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)) + { + Log.Message($" - 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) + { + Log.Error($"[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)) + { + Log.Error($"[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(); + + 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)) + { + Log.Warning($"[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)) + { + Log.Error($"[QuestNode_WriteToEventVariablesWithAdd] Increment operation failed: {ex.Message}"); + } + return currentValue; + } + } + + private object HandleTypeMismatch(object currentValue, object sourceValue, string mismatchReason, Slate slate) + { + if (logDebug.GetValue(slate)) + { + Log.Warning($"[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)) + { + Log.Message($" - 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; + } + } + } + } +} diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj index a38e8689..1e3e2219 100644 --- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj +++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj @@ -74,7 +74,335 @@ ..\..\..\..\..\..\common\RimWorld\RimWorldWin64_Data\Managed\UnityEngine.TextRenderingModule.dll False - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mod.vdf b/mod.vdf new file mode 100644 index 00000000..ea266338 --- /dev/null +++ b/mod.vdf @@ -0,0 +1,11 @@ + +"workshopitem" +{ + "appid" "294100" + "contentfolder" "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\WulaFallenEmpireV2" + "previewfile" "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\WulaFallenEmpireV2\\About\\Preview.png" + "visibility" "0" + "title" "Wula Fallen Empire V2" + "changenote" "1.6" + "publishedfileid" "3622186519" +} \ No newline at end of file