using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("0.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace DSPProliferatorTweak { internal static class IncCeilingTranspiler { private static readonly FieldInfo CargoIncTableField = AccessTools.Field(typeof(Cargo), "incTable"); private static readonly FieldInfo CeilingField = AccessTools.Field(typeof(ProliferatorTweakPlugin), "IncLevelAggregationCeiling"); internal static readonly MethodInfo AssemblerSplitInc = AccessTools.Method(typeof(AssemblerComponent), "split_inc_level", (Type[])null, (Type[])null); internal static readonly MethodInfo LabSplitInc = AccessTools.Method(typeof(LabComponent), "split_inc_level", (Type[])null, (Type[])null); internal static IEnumerable ReplaceTenBeforeSplitInc(IEnumerable instructions, MethodInfo splitMethod) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown List list = new List(instructions); int num = FindCallIndex(list, splitMethod); if (num < 0) { return list; } int num2 = Math.Max(0, num - 48); for (int num3 = num - 1; num3 >= num2; num3--) { if (IsLdcI4S10(list[num3])) { CodeInstruction val = list[num3]; CodeInstruction val2 = new CodeInstruction(OpCodes.Ldsfld, (object)CeilingField); foreach (Label label in val.labels) { val2.labels.Add(label); } foreach (ExceptionBlock block in val.blocks) { val2.blocks.Add(block); } list[num3] = val2; break; } } return list; } internal static IEnumerable ReplaceTenBeforeCargoIncTableRead(IEnumerable instructions) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown List list = new List(instructions); for (int num = list.Count - 1; num >= 0; num--) { if (!(list[num].opcode != OpCodes.Ldsfld) && list[num].operand == CargoIncTableField) { int num2 = Math.Max(0, num - 20); for (int num3 = num - 1; num3 >= num2; num3--) { if (IsLdcI4S10(list[num3])) { CodeInstruction val = list[num3]; CodeInstruction val2 = new CodeInstruction(OpCodes.Ldsfld, (object)CeilingField); foreach (Label label in val.labels) { val2.labels.Add(label); } foreach (ExceptionBlock block in val.blocks) { val2.blocks.Add(block); } list[num3] = val2; return list; } } } } return list; } private static int FindCallIndex(List list, MethodInfo splitMethod) { for (int i = 0; i < list.Count; i++) { if ((!(list[i].opcode != OpCodes.Call) || !(list[i].opcode != OpCodes.Callvirt)) && list[i].operand is MethodInfo methodInfo && methodInfo == splitMethod) { return i; } } return -1; } private static bool IsLdcI4S10(CodeInstruction c) { if (c.opcode != OpCodes.Ldc_I4_S) { return false; } object operand = c.operand; if (!(operand is sbyte b)) { if (operand is byte b2) { return b2 == 10; } return false; } return b == 10; } } [HarmonyPatch(typeof(AssemblerComponent), "InternalUpdate")] internal static class AssemblerIncCeilingPatch { [HarmonyTranspiler] internal static IEnumerable Transpiler(IEnumerable instructions) { return IncCeilingTranspiler.ReplaceTenBeforeSplitInc(instructions, IncCeilingTranspiler.AssemblerSplitInc); } } [HarmonyPatch(typeof(LabComponent), "InternalUpdateAssemble")] internal static class LabIncCeilingPatch { [HarmonyTranspiler] internal static IEnumerable Transpiler(IEnumerable instructions) { return IncCeilingTranspiler.ReplaceTenBeforeSplitInc(instructions, IncCeilingTranspiler.LabSplitInc); } } [HarmonyPatch(typeof(SpraycoaterComponent), "InternalUpdate")] internal static class SpraycoaterIncCeilingPatch { [HarmonyTranspiler] internal static IEnumerable Transpiler(IEnumerable instructions) { return IncCeilingTranspiler.ReplaceTenBeforeCargoIncTableRead(instructions); } } [HarmonyPatch(typeof(GameMain), "Start")] internal static class GameMainStartGenesisPatch { [HarmonyPostfix] internal static void Postfix() { ProliferatorTweakPlugin.NotifyGameStarted(); } } [HarmonyPatch(typeof(ItemProto), "GetPropValue", new Type[] { typeof(int), typeof(StringBuilder), typeof(int) })] internal static class ItemProtoTooltipGuard { [HarmonyPrefix] internal static void Prefix(ItemProto __instance) { int ability = __instance.Ability; if (ability > 0 && (Cargo.incTable == null || ability >= Cargo.incTable.Length)) { ProliferatorTweakPlugin.Instance?.EnsureCargoCoversAbilityIndex(ability); } } } [BepInPlugin("DSP.Kawaayi.ProliferatorTweak", "DSP Proliferator Tweak", "1.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class ProliferatorTweakPlugin : BaseUnityPlugin { public const string PluginGuid = "DSP.Kawaayi.ProliferatorTweak"; public const string PluginName = "DSP Proliferator Tweak"; public const string PluginVersion = "1.2.0"; public static int IncLevelAggregationCeiling = 10; private const int VanillaTableLength = 11; private const int DefaultCustomSlot = 11; private ConfigEntry _customAbilitySlot; private ConfigEntry _slotIncTenths; private ConfigEntry _slotAccTenths; private ConfigEntry _slotPowerTenths; private ConfigEntry _patchGenesisProliferator; private ConfigEntry _genesisItemId; private ConfigEntry _setGenesisSprayTimesHpMax; private ConfigEntry _genesisSprayTimesHpMax; private int[]? _vanillaInc; private int[]? _vanillaAcc; private int[]? _vanillaPower; private double[]? _vanillaIncMilli; private double[]? _vanillaAccMilli; private double[]? _vanillaPowerRatio; private int[]? _vanillaIncFastNum; private byte[]? _vanillaFastIncArrow; private Harmony? _harmony; public static ProliferatorTweakPlugin? Instance { get; private set; } private void Awake() { //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Expected O, but got Unknown //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Expected O, but got Unknown Instance = this; _customAbilitySlot = ((BaseUnityPlugin)this).Config.Bind("CustomSlot", "AbilityIndex", 11, "自定义增产档位下标(与 ItemProto.Ability 一致)。原版合法为 1~10;默认 11 表示在 Cargo 表末尾新增一档。若 ≤10 则只覆盖该格数据、不扩容表。"); _slotIncTenths = ((BaseUnityPlugin)this).Config.Bind("CustomSlot", "ExtraOutputTenths", 250, "该下标「额外产出」千分比×10 的整数(与原版 Cargo.incTable 一致):250 表示 +25.0%。"); _slotAccTenths = ((BaseUnityPlugin)this).Config.Bind("CustomSlot", "SpeedBonusTenths", 1000, "该下标「制造速度」千分比×10:1000 表示 +100.0%。"); _slotPowerTenths = ((BaseUnityPlugin)this).Config.Bind("CustomSlot", "ExtraPowerCostTenths", 1500, "该下标「额外耗电」千分比×10:1500 表示 +150.0%(可按需改)。"); _patchGenesisProliferator = ((BaseUnityPlugin)this).Config.Bind("GenesisBook", "SetGenesisItemAbility", true, "若为 true:尝试把创世之书物品 ItemProto.Ability 改为上面的自定义下标(默认物品 ID 1143)。"); _genesisItemId = ((BaseUnityPlugin)this).Config.Bind("GenesisBook", "ItemId", 1143, "要改 Ability 的物品 ID(默认创世增产剂 1143)。"); _setGenesisSprayTimesHpMax = ((BaseUnityPlugin)this).Config.Bind("GenesisBook", "SetItemSprayTimesHpMax", true, "若为 true:把该物品的 ItemProto.HpMax 设为下方数值。喷涂机用 HpMax 作为每次喷涂的「次数」基准(与物品说明里喷涂次数一致)。"); _genesisSprayTimesHpMax = ((BaseUnityPlugin)this).Config.Bind("GenesisBook", "SprayTimesHpMax", 60, new ConfigDescription("喷涂次数(写入 ItemProto.HpMax)。原版 Mk.I/II/III 增产约 12/24/60 量级,可按需调大。", (AcceptableValueBase)(object)new AcceptableValueRange(1, 99999), Array.Empty())); _customAbilitySlot.SettingChanged += delegate { FullApply(); }; _slotIncTenths.SettingChanged += delegate { FullApply(); }; _slotAccTenths.SettingChanged += delegate { FullApply(); }; _slotPowerTenths.SettingChanged += delegate { FullApply(); }; _patchGenesisProliferator.SettingChanged += delegate { FullApply(); }; _genesisItemId.SettingChanged += delegate { FullApply(); }; _setGenesisSprayTimesHpMax.SettingChanged += delegate { FullApply(); }; _genesisSprayTimesHpMax.SettingChanged += delegate { FullApply(); }; SnapshotVanilla(); _harmony = new Harmony("DSP.Kawaayi.ProliferatorTweak"); _harmony.PatchAll(typeof(ProliferatorTweakPlugin).Assembly); FullApply(); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} v{1}:下标={2} 增产‰×10={3} 加速‰×10={4} 耗电‰×10={5};喷涂HpMax={6}", "DSP Proliferator Tweak", "1.2.0", _customAbilitySlot.Value, _slotIncTenths.Value, _slotAccTenths.Value, _slotPowerTenths.Value, _setGenesisSprayTimesHpMax.Value ? _genesisSprayTimesHpMax.Value.ToString() : "不改")); } private void OnDestroy() { Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } Instance = null; } internal static void NotifyGameStarted() { Instance?.ApplyGenesisItemOnly(); } private void FullApply() { ApplyCargoTablesAndCeiling(); ApplyGenesisItemOnly(); } internal void EnsureCargoCoversAbilityIndex(int abilityIndex) { if (_vanillaInc != null && abilityIndex >= 0 && Cargo.incTable != null && abilityIndex >= Cargo.incTable.Length) { int value = _customAbilitySlot.Value; if (value >= 0 && value <= 63) { int needLen = Math.Max(11, Math.Max(value + 1, abilityIndex + 1)); EnsureTableLengths(needLen); IncLevelAggregationCeiling = Math.Max(IncLevelAggregationCeiling, Math.Max(10, Math.Max(value, abilityIndex))); WriteCustomSlotValues(); } } } private void ApplyGenesisItemOnly() { if ((!_patchGenesisProliferator.Value && !_setGenesisSprayTimesHpMax.Value) || (Object)(object)LDB.items == (Object)null) { return; } int value = _genesisItemId.Value; int value2 = _customAbilitySlot.Value; ItemProto val = ((ProtoSet)(object)LDB.items).Select(value); if (val != null && ((Proto)val).ID == value) { if (_patchGenesisProliferator.Value) { val.Ability = value2; } if (_setGenesisSprayTimesHpMax.Value) { val.HpMax = _genesisSprayTimesHpMax.Value; } } } private void ApplyCargoTablesAndCeiling() { if (_vanillaInc != null) { int value = _customAbilitySlot.Value; if (value < 0 || value > 63) { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"AbilityIndex={value} 超出安全范围,已忽略。"); return; } int needLen = Math.Max(11, value + 1); EnsureTableLengths(needLen); IncLevelAggregationCeiling = Math.Max(10, value); WriteCustomSlotValues(); } } private void WriteCustomSlotValues() { if (_vanillaInc != null && Cargo.incTable != null) { int value = _customAbilitySlot.Value; if (value >= 0 && value < Cargo.incTable.Length) { int num = Math.Max(0, _slotIncTenths.Value); int num2 = Math.Max(0, _slotAccTenths.Value); int num3 = Math.Max(0, _slotPowerTenths.Value); Cargo.incTable[value] = num; Cargo.accTable[value] = num2; Cargo.powerTable[value] = num3; Cargo.incTableMilli[value] = (double)num * 0.001; Cargo.accTableMilli[value] = (double)num2 * 0.001; Cargo.powerTableRatio[value] = 1.0 + (double)num3 * 0.001; } } } private void EnsureTableLengths(int needLen) { if (_vanillaInc != null && _vanillaAcc != null && _vanillaPower != null && _vanillaIncMilli != null && _vanillaAccMilli != null && _vanillaPowerRatio != null && _vanillaIncFastNum != null && _vanillaFastIncArrow != null && Cargo.incTable.Length < needLen) { Cargo.incTable = GrowArray(_vanillaInc, Cargo.incTable, needLen); Cargo.accTable = GrowArray(_vanillaAcc, Cargo.accTable, needLen); Cargo.powerTable = GrowArray(_vanillaPower, Cargo.powerTable, needLen); Cargo.incTableMilli = GrowArray(_vanillaIncMilli, Cargo.incTableMilli, needLen); Cargo.accTableMilli = GrowArray(_vanillaAccMilli, Cargo.accTableMilli, needLen); Cargo.powerTableRatio = GrowArray(_vanillaPowerRatio, Cargo.powerTableRatio, needLen); Cargo.incFastDivisionNumerator = GrowArray(_vanillaIncFastNum, Cargo.incFastDivisionNumerator, needLen); Cargo.fastIncArrowTable = GrowArray(_vanillaFastIncArrow, Cargo.fastIncArrowTable, needLen); } } private static int[] GrowArray(int[] snapshot, int[] current, int needLen) { if (current.Length >= needLen) { return current; } int[] array = new int[needLen]; Array.Copy(snapshot, array, snapshot.Length); int num = snapshot[^1]; for (int i = snapshot.Length; i < needLen; i++) { array[i] = num; } return array; } private static double[] GrowArray(double[] snapshot, double[] current, int needLen) { if (current.Length >= needLen) { return current; } double[] array = new double[needLen]; Array.Copy(snapshot, array, snapshot.Length); double num = snapshot[^1]; for (int i = snapshot.Length; i < needLen; i++) { array[i] = num; } return array; } private static byte[] GrowArray(byte[] snapshot, byte[] current, int needLen) { if (current.Length >= needLen) { return current; } byte[] array = new byte[needLen]; Array.Copy(snapshot, array, snapshot.Length); byte b = snapshot[^1]; for (int i = snapshot.Length; i < needLen; i++) { array[i] = b; } return array; } private void SnapshotVanilla() { _vanillaInc = (int[])Cargo.incTable.Clone(); _vanillaAcc = (int[])Cargo.accTable.Clone(); _vanillaPower = (int[])Cargo.powerTable.Clone(); _vanillaIncMilli = (double[])Cargo.incTableMilli.Clone(); _vanillaAccMilli = (double[])Cargo.accTableMilli.Clone(); _vanillaPowerRatio = (double[])Cargo.powerTableRatio.Clone(); _vanillaIncFastNum = (int[])Cargo.incFastDivisionNumerator.Clone(); _vanillaFastIncArrow = (byte[])Cargo.fastIncArrowTable.Clone(); } } }