From a40cb99745ba674ee50eb64d05b3bbec852cbb01 Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Sun, 8 Dec 2024 23:22:46 +0100 Subject: [PATCH] Add cykaOfqud --- Projects/CykaOfQud/CavesOfQud.csproj | 57 ++ Projects/CykaOfQud/Class1.cs | 121 ++++ Projects/CykaOfQud/CykaOfQud.sln | 16 + Projects/CykaOfQud/Patches.cs | 621 ++++++++++++++++++ Projects/CykaOfQud/Properties/AssemblyInfo.cs | 35 + Projects/CykaOfQud/sync | 1 + 6 files changed, 851 insertions(+) create mode 100644 Projects/CykaOfQud/CavesOfQud.csproj create mode 100644 Projects/CykaOfQud/Class1.cs create mode 100644 Projects/CykaOfQud/CykaOfQud.sln create mode 100644 Projects/CykaOfQud/Patches.cs create mode 100644 Projects/CykaOfQud/Properties/AssemblyInfo.cs create mode 100644 Projects/CykaOfQud/sync diff --git a/Projects/CykaOfQud/CavesOfQud.csproj b/Projects/CykaOfQud/CavesOfQud.csproj new file mode 100644 index 0000000..ad2edf1 --- /dev/null +++ b/Projects/CykaOfQud/CavesOfQud.csproj @@ -0,0 +1,57 @@ + + + + + C:/Games/Caves.of.Qud.Build.16668101 + $(GAME_DIR)/CoQ_Data/Managed + $(GAME_DIR)/BepInEx + Debug + AnyCPU + {EE5EFB7F-A4DC-44F0-967B-F71ECA2D46AE} + Library + Properties + CykaOfQud + CykaOfQud + v4.8.1 + 512 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + $(GAME_BEPINEX)/core/0Harmony.dll + + + $(GAME_BEPINEX)/core/BepInEx.dll + + + $(GAME_MANAGED)/UnityEngine.dll + + + $(GAME_MANAGED)/UnityEngine.CoreModule.dll + + + + \ No newline at end of file diff --git a/Projects/CykaOfQud/Class1.cs b/Projects/CykaOfQud/Class1.cs new file mode 100644 index 0000000..a3d87e6 --- /dev/null +++ b/Projects/CykaOfQud/Class1.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using BepInEx; +using BepInEx.Configuration; +using HarmonyLib; +using HarmonyLib.Tools; + +namespace CykaOfQud { + [BepInPlugin(pluginGuid, pluginName, pluginVersion)] + public class Main : BaseUnityPlugin { + private const string pluginGuid = "CykaOfQud"; + private const string pluginName = "CykaOfQud"; + private const string pluginVersion = "1.0.0"; + + public static ConfigEntry excavatorCapacityMultiplier; + public static ConfigEntry excavatorMineTileIterationsMultiplier; + public static ConfigEntry truckCapacityMultiplier; + public static ConfigEntry cargoShipCapacityMultiplier; + public static ConfigEntry excavatorMiningCapacityMultiplier; + public static ConfigEntry excavatorMiningAreaMultiplier; + public static ConfigEntry excavatorMinReachMultiplier; + public static ConfigEntry excavatorMaxReachMultiplier; + public static ConfigEntry bufferCapacityMultiplier; + public static ConfigEntry unityGenerationMultiplier; + public static ConfigEntry depotTransferSpeedMultiplier; + public static ConfigEntry worldMineSpeedMultiplier; + public static ConfigEntry housingCapacityMultiplier; + public static ConfigEntry dumpDelayMultiplier; + public static ConfigEntry transportSpeedMultiplier; + public static ConfigEntry shipyardCargoMultiplier; + public static ConfigEntry autosaveInterval; + public static ConfigEntry recipeMultipliers; + public static Dictionary recipeMultipliersDict; + + public static ConfigEntry debugMode; + + public void Awake() { + excavatorCapacityMultiplier = Config.Bind("General", "Excavator Capacity Multiplier", 1, + new ConfigDescription("Excavator Capacity Multiplier")); + excavatorMineTileIterationsMultiplier = Config.Bind("General", "Excavator Mine Tile Iterations Multiplier", + 1f, + new ConfigDescription("Excavator Mine Tile Iterations Multiplier")); + truckCapacityMultiplier = Config.Bind("General", "Truck Capacity Multiplier", 1, + new ConfigDescription("Truck Capacity Multiplier")); + cargoShipCapacityMultiplier = Config.Bind("General", "Cargo Ship Capacity Multiplier", 1, + new ConfigDescription("Cargo Ship Capacity Multiplier")); + excavatorMiningAreaMultiplier = Config.Bind("General", "Excavator Mining Area Multiplier", 1, + new ConfigDescription("Excavator Mining Area Multiplier")); + excavatorMiningCapacityMultiplier = Config.Bind("General", "Excavator Mining Capacity Multiplier", 1f, + new ConfigDescription("Excavator Mining Capacity Multiplier")); + excavatorMinReachMultiplier = Config.Bind("General", "Excavator Min Reach Multiplier", 1f, + new ConfigDescription("Excavator Min Reach Multiplier")); + excavatorMaxReachMultiplier = Config.Bind("General", "Excavator Max Reach Multiplier", 1f, + new ConfigDescription("Excavator Max Reach Multiplier")); + bufferCapacityMultiplier = Config.Bind("General", "Buffer Capacity Multiplier", 1f, + new ConfigDescription("Buffer Capacity Multiplier")); + storageCapacityMultiplier = Config.Bind("General", "Storage Capacity Multiplier", 1f, + new ConfigDescription("Storage Capacity Multiplier")); + unityGenerationMultiplier = Config.Bind("General", "Unity Generation Multiplier", 1f, + new ConfigDescription("Unity Generation Multiplier")); + depotTransferSpeedMultiplier = Config.Bind("General", "Depot Transfer Speed Multiplier", 1f, + new ConfigDescription("Depot Transfer Speed Multiplier")); + worldMineSpeedMultiplier = Config.Bind("General", "World Mine Speed Multiplier", 1f, + new ConfigDescription("World Mine Speed Multiplier")); + housingCapacityMultiplier = Config.Bind("General", "Housing Capacity Multiplier", 1f, + new ConfigDescription("Housing Capacity Multiplier")); + dumpDelayMultiplier = Config.Bind("General", "Dump Delay Multiplier", 1f, + new ConfigDescription("Dump Delay Multiplier")); + transportSpeedMultiplier = Config.Bind("General", "Transport Speed Multiplier", 1f, + new ConfigDescription("Transport Speed Multiplier")); + shipyardCargoMultiplier = Config.Bind("General", "Shipyard Cargo Multiplier", 1f, + new ConfigDescription("Shipyard Cargo Multiplier")); + autosaveInterval = Config.Bind("General", "Autosave Interval", 1, + new ConfigDescription("Autosave Interval in minutes")); + recipeMultipliers = Config.Bind("General", "Recipe Multipliers", "dirt:4", + new ConfigDescription("Recipe Multipliers")); + + recipeMultipliersDict = recipeMultipliers.Value.Split(',') + .ToDictionary(x => x.Split(':')[0], x => int.Parse(x.Split(':')[1])); + recipeMultipliers.SettingChanged += (sender, args) => { + recipeMultipliersDict = recipeMultipliers.Value.Split(',') + .ToDictionary(x => x.Split(':')[0], x => int.Parse(x.Split(':')[1])); + Console.WriteLine("IndustrialCyka: Recipe multipliers parsed as:"); + foreach (var kvp in recipeMultipliersDict) + Console.WriteLine("\tIndustrialCyka: {0} x {1}", kvp.Key, kvp.Value); + }; + + debugMode = Config.Bind("General", "Debug Mode", false, new ConfigDescription("Debug Mode")); + + // shootingSpeedMultiplier.SettingChanged += (sender, args) => WeaponPropertiesManager.DoPatch(); + // energyGenMultiplier.SettingChanged += (sender, args) => GeneratorPropertiesManager.DoPatch(); + // magnetStrenghtMultiplier.SettingChanged += (sender, args) => MagnetPropertiesManager.DoPatch(); + // magnetRadiusMultiplier.SettingChanged += (sender, args) => MagnetPropertiesManager.DoPatch(); + // beamStrenghtMultiplier.SettingChanged += (sender, args) => BeamPropertiesManager.DoPatch(); + // beamRadiusMultiplier.SettingChanged += (sender, args) => BeamPropertiesManager.DoPatch(); + // fuelTankRefillMultiplier.SettingChanged += (sender, args) => FuelPropertiesManager.DoPatch(); + // fuelTankCapacityMultiplier.SettingChanged += (sender, args) => FuelPropertiesManager.DoPatch(); + // wheelTorqueMultiplier.SettingChanged += (sender, args) => WheelPropertiesManager.DoPatch(); + // wheelSpeedMultiplier.SettingChanged += (sender, args) => WheelPropertiesManager.DoPatch(); + // jetThrustMultiplier.SettingChanged += (sender, args) => ThrusterPropertiesManager.DoPatch(); + // minerGroundArea.SettingChanged += (sender, args) => MinerPropertiesManager.DoPatch(); + // minerMiningSpeed.SettingChanged += (sender, args) => MinerPropertiesManager.DoPatch(); + // wirelessChargingPowerPerArcMultiplier.SettingChanged += (sender, args) => WirelessChargerPropertiesManager.DoPatch(); + // wirelessChargingArcFiringIntervalMultiplier.SettingChanged += (sender, args) => WirelessChargerPropertiesManager.DoPatch(); + // wirelessChargingRadiusMultiplier.SettingChanged += (sender, args) => WirelessChargerPropertiesManager.DoPatch(); + + Logger.LogInfo("Cyka mod loaded"); + HarmonyFileLog.Enabled = true; + Harmony harmony = new Harmony(pluginGuid); + harmony.PatchAll(); + var originalMethods = harmony.GetPatchedMethods(); + Logger.LogInfo("Patched " + originalMethods.Count() + " methods"); + foreach (var method in originalMethods) { + Logger.LogInfo("Patched " + method.Name); + } + } + + public static ConfigEntry storageCapacityMultiplier; + } +} \ No newline at end of file diff --git a/Projects/CykaOfQud/CykaOfQud.sln b/Projects/CykaOfQud/CykaOfQud.sln new file mode 100644 index 0000000..111ba7b --- /dev/null +++ b/Projects/CykaOfQud/CykaOfQud.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CavesOfQud", "CavesOfQud.csproj", "{EE5EFB7F-A4DC-44F0-967B-F71ECA2D46AE}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EE5EFB7F-A4DC-44F0-967B-F71ECA2D46AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EE5EFB7F-A4DC-44F0-967B-F71ECA2D46AE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EE5EFB7F-A4DC-44F0-967B-F71ECA2D46AE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EE5EFB7F-A4DC-44F0-967B-F71ECA2D46AE}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/Projects/CykaOfQud/Patches.cs b/Projects/CykaOfQud/Patches.cs new file mode 100644 index 0000000..1ac58b5 --- /dev/null +++ b/Projects/CykaOfQud/Patches.cs @@ -0,0 +1,621 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection.Emit; +using HarmonyLib; +using Mafi; +using Mafi.Collections.ImmutableCollections; +using Mafi.Core; +using Mafi.Core.Buildings.Cargo.Modules; +using Mafi.Core.Buildings.Cargo.Ships.Modules; +using Mafi.Core.Buildings.Settlements; +using Mafi.Core.Buildings.Shipyard; +using Mafi.Core.Buildings.Storages; +using Mafi.Core.Entities; +using Mafi.Core.Entities.Dynamic; +using Mafi.Core.Entities.Static; +using Mafi.Core.Entities.Static.Layout; +using Mafi.Core.Factory.Machines; +using Mafi.Core.Factory.Recipes; +using Mafi.Core.Factory.Transports; +using Mafi.Core.Population; +using Mafi.Core.Ports.Io; +using Mafi.Core.Products; +using Mafi.Core.Prototypes; +using Mafi.Core.SaveGame; +using Mafi.Core.Terrain; +using Mafi.Core.Vehicles.Excavators; +using Mafi.Core.World.Entities; + +namespace CykaOfIndustry { + [HarmonyPatch] + public class Patches { + [HarmonyPrefix] + [HarmonyPatch(typeof(ExcavatorProtoBuilder.ExcavatorProtoBuilderState), "SetCapacity")] + static void excavatorCapacityMultiplier(ref int quantity) { + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Old excavator capacity {0}", quantity); + quantity *= Main.excavatorCapacityMultiplier.Value; + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: New excavator capacity {0}", quantity); + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(ExcavatorProtoBuilder.ExcavatorProtoBuilderState), "SetMinedThicknessByDistanceMeters")] + static void excavatorMiningAreaMultiplier(ref float[] thicknessMeters) { + for (int i = 0; i < thicknessMeters.Length; i++) { + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Old mining area {0}", thicknessMeters[i]); + thicknessMeters[i] *= Main.excavatorMiningCapacityMultiplier.Value; + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: New mining area {0}", thicknessMeters[i]); + } + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(ExcavatorProtoBuilder.ExcavatorProtoBuilderState), "SetMaxMiningDistance")] + static void excavatorReachMultiplier(ref RelTile1i minMiningDistance, ref RelTile1i maxMiningDistance) { + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Old min mining distance {0}, max mining distance {1}", + minMiningDistance, maxMiningDistance); + minMiningDistance = new RelTile1i((int)(minMiningDistance.Value * Main.excavatorMinReachMultiplier.Value)); + maxMiningDistance = new RelTile1i((int)(maxMiningDistance.Value * Main.excavatorMaxReachMultiplier.Value)); + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: New min mining distance {0}, max mining distance {1}", + minMiningDistance, maxMiningDistance); + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(TruckProtoBuilder.TruckProtoBuilderState), "SetCapacity")] + static void truckCapacityMultiplier(ref int quantity) { + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Old truck capacity {0}", quantity); + quantity *= Main.truckCapacityMultiplier.Value; + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: New truck capacity {0}", quantity); + } + + // [HarmonyPrefix] + // [HarmonyPatch(typeof(StorageProtoBuilder.State), "SetCapacity")] + // static void storageCapacityMultiplier(ref int capacity) { +// // Console.WriteLine("IndustrialCyka: Old storage capacity: {0}", capacity); + // capacity = (int)(capacity * Main.storageCapacityMultiplier.Value); +// // Console.WriteLine("IndustrialCyka: New storage capacity: {0}", capacity); + // } + + [HarmonyPostfix] + [HarmonyPatch(typeof(CargoShipModuleProto), MethodType.Constructor, + new[] { + typeof(Proto.ID), typeof(Proto.Str), typeof(ProductType), typeof(Quantity), + typeof(CargoShipModuleProto.Gfx) + })] + static void cargoShipCapacityMultiplier(CargoShipModuleProto __instance) { + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Old ship capacity {0}", __instance.Capacity); + __instance.Capacity = new Quantity(__instance.Capacity.Value * Main.cargoShipCapacityMultiplier.Value); + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: New ship capacity {0}", __instance.Capacity); + } + + // No workey... idk how it's supposed to work, speed is always 1 or 100% + // [HarmonyPrefix] + // [HarmonyPatch(typeof(DrivingEntity), "SetSpeedFactor")] + // static void vehicleSpeedMultiplier(ref Percent speedFactor) { +// // Console.WriteLine("IndustrialCyka: Old speed: {0}", speedFactor.ToString()); + // // typeof(Percent) + // // .GetField("RawValue",BindingFlags.Instance|BindingFlags.NonPublic) + // // .SetValue(speedFactor,speedFactor.ToFloat() / Main.vehicleSpeedMultiplier.Value); + // Percent newSpeedFactor = Percent.FromFloat(speedFactor.ToFloat() / Main.vehicleSpeedMultiplier.Value); + // speedFactor = newSpeedFactor; +// // Console.WriteLine("IndustrialCyka: New speed: {1}", newSpeedFactor.RawValue.ToString()); + // } + +// [HarmonyPostfix] +// [HarmonyPatch(typeof(SmoothDriver), "SetSpeedFactor")] +// static void vehicleSpeedMultiplier(SmoothDriver __instance) { +// Fix32 speedMulti = Fix32.FromFloat(Main.vehicleSpeedMultiplier.Value); +// +// Traverse traverse = Traverse.Create(__instance); +// Traverse maxForwardsSpeedField = traverse.Field("m_maxForwardsSpeed"); +// Traverse maxBackwardsSpeedField = traverse.Field("m_maxBackwardsSpeed"); +// Traverse maxAccelerationField = traverse.Field("m_maxAcceleration"); +// +// // Console.WriteLine("IndustrialCyka: Old speeds: (F) {0}, (B) {1}, (A) {2}", maxForwardsSpeedField.GetValue(), +// // maxBackwardsSpeedField.GetValue(), maxAccelerationField.GetValue()); +// +// maxForwardsSpeedField.SetValue((Fix32)maxForwardsSpeedField.GetValue() * speedMulti); +// maxBackwardsSpeedField.SetValue((Fix32)maxBackwardsSpeedField.GetValue() * speedMulti); +// maxAccelerationField.SetValue((Fix32)maxAccelerationField.GetValue() * speedMulti); +// +// // Console.WriteLine("IndustrialCyka: New speeds: (F) {0}, (B) {1}, (A) {2}", maxForwardsSpeedField.GetValue(), +// // maxBackwardsSpeedField.GetValue(), maxAccelerationField.GetValue()); +// } + + [HarmonyPostfix] + [HarmonyPatch(typeof(StorageBaseProto), MethodType.Constructor, + new[] { + typeof(StaticEntityProto.ID), + typeof(Proto.Str), + typeof(EntityLayout), + typeof(Quantity), + typeof(EntityCosts), + typeof(LayoutEntityProto.Gfx), + typeof(Quantity), + typeof(Duration), + typeof(IEnumerable) + })] + static void storageCapacityMultiplier(StorageProto __instance) { + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Old storage capacity {0}", __instance.Capacity); + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Old storage transfer limit {0}", __instance.TransferLimit); + Traverse traverse = Traverse.Create(__instance); + + traverse.Field("Capacity") + .SetValue(new Quantity((int)(__instance.Capacity.Value * Main.storageCapacityMultiplier.Value))); + traverse.Field("TransferLimit").SetValue(new Quantity(10000)); + traverse.Field("TransferLimitDuration").SetValue(Duration.FromTicks(1)); + + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: New storage capacity {0}", __instance.Capacity); + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: New storage transfer limit {0}", __instance.TransferLimit); + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(UpointsManager), "GenerateUnity")] + static void unityGenerationMultiplier(Proto.ID categoryId, ref Upoints generated) { + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Old generated {0} unity", generated.Value); + Fix32 multi = Fix32.FromFloat(Main.unityGenerationMultiplier.Value); + generated = new Upoints(generated.Value * multi); + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: New generated {0} unity", generated.Value); + } + + [HarmonyTranspiler] + [HarmonyPatch(typeof(Machine), "updateWorkOnRecipes")] + static IEnumerable unityBooster(IEnumerable instructions) { + Dictionary matchTable = new Dictionary(); + matchTable[0] = OpCodes.Ldsfld; + matchTable[1] = OpCodes.Br; + matchTable[2] = OpCodes.Ldc_I4_2; + int matches = 0; + int totalMatch = matchTable.Count; + + var codes = new List(instructions); + for (int i = 0; i < codes.Count; i++) { + if (matches >= totalMatch) { + break; + } + + if (codes[i].opcode.Equals(matchTable[matches])) { + if (matches == totalMatch - 1) { + codes[i].opcode = OpCodes.Ldc_I4_6; + } + + matches++; + } + } + + // for (int i = 0; i < codes.Count; i++) { + // Console.WriteLine(codes[i].ToString()); + // } + + return codes.AsEnumerable(); + } + + // Could not make this work either... idk why... Doesn't make sense... + // [HarmonyPostfix] + // [HarmonyPatch(typeof(SimpleVirtualResource), "MineResourceAt")] + // static void infiniteGroundResources(SimpleVirtualResource __instance) { +// // Console.WriteLine("IndustrialCyka: Patching ground resources (Capacity)"); + // Traverse traverse = Traverse.Create(__instance); + // Traverse capacityField = traverse.Field("Capacity"); + // capacityField.SetValue(1000000000); + // Traverse quantityField = traverse.Field("Quantity"); + // quantityField.SetValue(1000000000); + // } + + [HarmonyPrefix] + [HarmonyPatch(typeof(ProductBuffer), "ForceNewCapacityTo")] + static void bufferCapacityMultiplier(ref Quantity newCapacity) { + if (newCapacity.Value <= 0) { + return; + } + + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Old buffer capacity {0}", newCapacity); + Quantity newNewCapacity = new Quantity((int)(newCapacity.Value * Main.bufferCapacityMultiplier.Value)); + newCapacity = newNewCapacity; + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: New buffer capacity {0}", newCapacity); + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(CargoDepotModuleProto), MethodType.Constructor, + new[] { + typeof(CargoDepotModuleProto.ID), + typeof(Proto.Str), + typeof(EntityLayout), + typeof(ProductType), + typeof(Option), + typeof(Quantity), + typeof(Quantity), + typeof(Duration), + typeof(Electricity), + typeof(bool), + typeof(Percent), + typeof(EntityCosts), + typeof(CargoDepotModuleProto.Gfx), + typeof(IEnumerable), + })] + static void depotTransferSpeedMultiplier(CargoDepotModuleProto __instance) { + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Old depot transfer speed {0}", __instance.QuantityPerExchange); + Traverse traverse = Traverse.Create(__instance); + + traverse.Field("QuantityPerExchange") + .SetValue(new Quantity((int)(__instance.QuantityPerExchange.Value * + Main.depotTransferSpeedMultiplier.Value))); + + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: New depot transfer speed {0}", __instance.QuantityPerExchange); + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(WorldMapMineProto), MethodType.Constructor, + new[] { + typeof(EntityProto.ID), + typeof(Proto.Str), + typeof(ProductQuantity), + typeof(Duration), + typeof(Upoints), + typeof(UpointsCategoryProto), + typeof(EntityCosts), + typeof(Func), + typeof(int), + typeof(Quantity), + typeof(WorldMapEntityProto.Gfx), + typeof(int), + typeof(int), + typeof(IEnumerable), + })] + static void worldMineSpeedMultiplier(WorldMapMineProto __instance) { + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Old world mine speed {0}", + __instance.ProducedProductPerStep.Quantity); + ProductQuantity newProductQuantity = new ProductQuantity(__instance.ProducedProductPerStep.Product, + new Quantity((int)(__instance.ProducedProductPerStep.Quantity.Value * + Main.worldMineSpeedMultiplier.Value))); + + Traverse.Create(__instance) + .Field("ProducedProductPerStep") + .SetValue(newProductQuantity); + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: New world mine speed {0}", + __instance.ProducedProductPerStep.Quantity); + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(WorldMapMineProto), MethodType.Constructor, + new[] { + typeof(EntityProto.ID), + typeof(Proto.Str), + typeof(ProductQuantity), + typeof(Duration), + typeof(Upoints), + typeof(UpointsCategoryProto), + typeof(EntityCosts), + typeof(Func), + typeof(int), + typeof(Quantity), + typeof(WorldMapEntityProto.Gfx), + typeof(int), + typeof(int), + typeof(IEnumerable), + })] + static void worldMineLevelIncrementMultiplier(WorldMapMineProto __instance) { + Traverse traverse = Traverse.Create(__instance); + + // int level = traverse.Field("Level").GetValue(); + int maxLevel = traverse.Field("MaxLevel").GetValue(); + // int levelsPerUpgrade = traverse.Field("LevelsPerUpgrade").GetValue(); + + int newLevelsPerUpgrade = 10; + int newMaxLevel = (int)Math.Ceiling((double)maxLevel / newLevelsPerUpgrade) * newLevelsPerUpgrade; + + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Old max level {0}, new max level {1}", maxLevel, newMaxLevel); + traverse.Field("MaxLevel").SetValue(newMaxLevel); + traverse.Field("LevelsPerUpgrade").SetValue(newLevelsPerUpgrade); + } + + [HarmonyTranspiler] + [HarmonyPatch(typeof(WorldMapMineProto), MethodType.Constructor, + new[] { + typeof(EntityProto.ID), + typeof(Proto.Str), + typeof(ProductQuantity), + typeof(Duration), + typeof(Upoints), + typeof(UpointsCategoryProto), + typeof(EntityCosts), + typeof(Func), + typeof(int), + typeof(Quantity), + typeof(WorldMapEntityProto.Gfx), + typeof(int), + typeof(int), + typeof(IEnumerable), + })] + static IEnumerable cookWorldMineLevelIncrementMultiplier( + IEnumerable instructions) { + Dictionary matchTable = new Dictionary(); + matchTable[0] = OpCodes.Rem; + matchTable[1] = OpCodes.Ldfld; + matchTable[2] = OpCodes.Ldarg_0; + matchTable[3] = OpCodes.Ldfld; + matchTable[4] = OpCodes.Ldarg_0; + int matches = 0; + int totalMatch = matchTable.Count; + + var codes = new List(instructions); + for (int i = codes.Count - 1; i >= 0; i--) { + if (matches >= totalMatch) { + break; + } + + if (codes[i].opcode.Equals(matchTable[matches])) { + if (matches == totalMatch - 1) { + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Patching world mine level increment"); + codes[i + 4].opcode = OpCodes.Add; + codes[i + 5].opcode = OpCodes.Brtrue_S; + break; + } + + matches++; + } + else { + matches = 0; + } + } + + return codes.AsEnumerable(); + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(SettlementHousingModuleProto), MethodType.Constructor, new[] { + typeof(StaticEntityProto.ID), + typeof(Proto.Str), + typeof(EntityLayout), + typeof(EntityCosts), + typeof(int), + typeof(Upoints), + typeof(ImmutableArray, Percent>>), + typeof(IReadOnlyDictionary), + typeof(Option), + typeof(SettlementHousingModuleProto.Gfx), + })] + static void housingCapacityMultiplier(SettlementHousingModuleProto __instance) { + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Old housing capacity {0}", __instance.Capacity); + Traverse.Create(__instance).Field("Capacity").Value = + (int)(__instance.Capacity * Main.housingCapacityMultiplier.Value); + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: New housing capacity {0}", __instance.Capacity); + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(StackerProto), MethodType.Constructor, new[] { + typeof(StaticEntityProto.ID), + typeof(Proto.Str), + typeof(EntityLayout), + typeof(EntityCosts), + typeof(Electricity), + typeof(ThicknessTilesI), + typeof(RelTile3i), + typeof(Duration), + typeof(Duration), + typeof(StackerProto.Gfx), + typeof(ThicknessTilesI), + typeof(IEnumerable), + })] + static void dumpDelayMultiplier(StackerProto __instance) { + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Old dumpDelay {0}", __instance.DumpDelay); + Duration newDelay = + new Duration(Math.Max((int)(__instance.DumpDelay.Ticks * Main.dumpDelayMultiplier.Value), 1)); + Traverse.Create(__instance).Field("DumpDelay").SetValue(newDelay); + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: New dumpDelay {0}", __instance.DumpDelay); + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(TransportProto), MethodType.Constructor, new[] { + typeof(StaticEntityProto.ID), + typeof(Proto.Str), + typeof(ThicknessTilesF), + typeof(Quantity), + typeof(RelTile1f), + typeof(RelTile1f), + typeof(RelTile1i), + typeof(bool), + typeof(bool), + typeof(Option), + typeof(RelTile1i), + typeof(IoPortShapeProto), + typeof(Electricity), + typeof(Percent), + typeof(bool), + typeof(bool), + typeof(EntityCosts), + typeof(RelTile1i), + typeof(Duration), + typeof(Option), + typeof(VirtualProductProto), + typeof(Quantity), + typeof(TransportProto.Gfx), + })] + static void transportSpeedMultiplier(ref StaticEntityProto.ID id, ref Proto.Str strings, + ref ThicknessTilesF surfaceRelativeHeight, ref Quantity maxQuantityPerTransportedProduct, + ref RelTile1f transportedProductsSpacing, ref RelTile1f speedPerTick, ref RelTile1i zStepLength, + ref bool needsPillarsAtGround, ref bool canBeBuried, + ref Option tileSurfaceWhenOnGround, ref RelTile1i maxPillarSupportRadius, + ref IoPortShapeProto portsShape, ref Electricity baseElectricityCost, ref Percent cornersSharpnessPercent, + ref bool allowMixedProducts, ref bool isBuildable, ref EntityCosts costs, ref RelTile1i lengthPerCost, + ref Duration constructionDurationPerProduct, ref Option nextTier, + ref VirtualProductProto maintenanceProduct, Quantity maintenancePerTile, ref TransportProto.Gfx graphics) { + if (TransportPillarProto.MAX_PILLAR_HEIGHT.Value < 25) + typeof(TransportPillarProto).GetField("MAX_PILLAR_HEIGHT").SetValue(null, new ThicknessTilesI(25)); + if (IoPort.MAX_TRANSFER_PER_TICK.Value < 10000) + typeof(IoPort).GetField("MAX_TRANSFER_PER_TICK").SetValue(null, new Quantity(10000)); + + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Old maxQuantityPerTransportedProduct {0}", + maxQuantityPerTransportedProduct); + maxQuantityPerTransportedProduct *= 1000; + maxQuantityPerTransportedProduct = maxQuantityPerTransportedProduct.Min(new Quantity(10000)); + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: New maxQuantityPerTransportedProduct {0}", + maxQuantityPerTransportedProduct); + + speedPerTick *= 10; + transportedProductsSpacing = speedPerTick; + zStepLength = RelTile1i.One; + canBeBuried = true; + maxPillarSupportRadius = new RelTile1i(8); + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(ShipyardProto), MethodType.Constructor, new[] { + typeof(StaticEntityProto.ID), + typeof(Proto.Str), + typeof(EntityLayout), + typeof(EntityCosts), + typeof(bool), + typeof(Quantity), + typeof(Option), + typeof(ImmutableArray>), + typeof(StackerProto.Gfx), + typeof(ImmutableArray), + typeof(bool), + })] + static void shipyardCargoMultiplier(ShipyardProto __instance) { + Traverse.Create(__instance).Field("CargoCapacity").SetValue(new Quantity( + (int)(__instance.CargoCapacity.Value * Main.shipyardCargoMultiplier.Value))); + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(SaveManager), "isTimeForAutoSave")] + static void autosaveInterval(ref bool __result, SaveManager __instance) { + if (Main.autosaveInterval.Value <= 0) { + __result = false; + return; + } + + var trav = Traverse.Create(__instance); + var lastSaveTime = trav.Field("m_lastSaveTime").GetValue(); + var num = (Environment.TickCount - lastSaveTime).Abs() / 1000L; + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Autosave interval: {0}", num); + __result = num > Main.autosaveInterval.Value; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(MachineProto), nameof(MachineProto.AddRecipe))] + static void machineProtoAddRecipe(MachineProto __instance, ref RecipeProto recipe) { + Console.WriteLine("Recipe outputs for {0}:", __instance.Id); + recipe.AllOutputs.ForEach(o => { + var id = o.Product.Id.ToString(); + Console.WriteLine("\tIndustrialCyka: Recipe output {0} x {1}", id, o.Quantity); + if (!Main.recipeMultipliersDict.ContainsKey(id)) { + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Recipe output {0} not found in multipliers, nothing to do", id); + return; + } + var multiplier = Main.recipeMultipliersDict[id]; + var trav = Traverse.Create(o); + trav.Field("Quantity").SetValue(new Quantity(trav.Field("Quantity").GetValue().Value * multiplier)); + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Recipe output {0} changed to {1}", id, trav.Field("Quantity").GetValue()); + }); + } + } + + [HarmonyPatch(typeof(Excavator), "MineMixedAt")] + public class MineMixedAtPatch { + public static Dictionary + originalCapacity = new Dictionary(); + + public static Dictionary> originalMinedThicknessByDistance = + new Dictionary>(); + + public static Dictionary originalMineTileIterations = + new Dictionary(); + + public static Dictionary originalMaxMiningDistance = + new Dictionary(); + + static void Prefix(ref Excavator __instance) { + if (!originalCapacity.ContainsKey(__instance.Prototype)) { + originalCapacity.Add(__instance.Prototype, __instance.Prototype.Capacity); + } + + var trav = Traverse.Create(__instance.Prototype); + trav.Field("Capacity") + .SetValue(new Quantity(originalCapacity[__instance.Prototype].Value * + Main.excavatorCapacityMultiplier.Value)); + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Excavator capacity: {0}", __instance.Prototype.Capacity.Value); + + if (!originalMinedThicknessByDistance.ContainsKey(__instance.Prototype)) { + originalMinedThicknessByDistance.Add(__instance.Prototype, + trav.Field("MinedThicknessByDistance").GetValue>()); + } + + trav.Field("MinedThicknessByDistance") + .SetValue(originalMinedThicknessByDistance[__instance.Prototype] + .SelectMany(t => Enumerable.Repeat(t, Main.excavatorMiningAreaMultiplier.Value)) + .Select(t => + new ThicknessTilesF((int)(t.Value.ToFloat() * Main.excavatorMiningCapacityMultiplier.Value))) + .ToImmutableArray()); + if (Main.debugMode.Value) + originalMinedThicknessByDistance[__instance.Prototype].ForEach(t => Console.WriteLine(t.Value)); + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Excavator mined thickness: {0}", + __instance.Prototype.MinedThicknessByDistance); + + if (!originalMaxMiningDistance.ContainsKey(__instance.Prototype)) { + originalMaxMiningDistance.Add(__instance.Prototype, + trav.Field("MaxMiningDistance").GetValue()); + } + + var value = originalMaxMiningDistance[__instance.Prototype]; + var newValueMiningDistance = new RelTile1i((int)(value.Value * Main.excavatorMaxReachMultiplier.Value)); + trav.Field("MaxMiningDistance") + .SetValue(newValueMiningDistance); + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Excavator max mining distance: {0}", + __instance.Prototype.MaxMiningDistance); + + var trav2 = Traverse.Create(__instance.Prototype.MineTimings); + if (!originalMineTileIterations.ContainsKey(__instance.Prototype.MineTimings)) { + originalMineTileIterations.Add(__instance.Prototype.MineTimings, + trav2.Field("MineTileIterations").GetValue()); + } + + var newValue = (int)(originalMineTileIterations[__instance.Prototype.MineTimings] * + Main.excavatorMineTileIterationsMultiplier.Value); + trav2.Field("MineTileIterations").SetValue(newValue); + trav2.Field("PrepareToMineDuration").SetValue(new Duration(1)); + trav2.Field("MineDuration").SetValue(new Duration(1)); + trav2.Field("PrepareToDumpDuration").SetValue(new Duration(1)); + trav2.Field("DumpDuration").SetValue(new Duration(1)); + if (Main.debugMode.Value) + Console.WriteLine("IndustrialCyka: Excavator mine tile iterations 2: {0}", + trav2.Field("MineTileIterations").GetValue()); + } + } +} \ No newline at end of file diff --git a/Projects/CykaOfQud/Properties/AssemblyInfo.cs b/Projects/CykaOfQud/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..6cff8c4 --- /dev/null +++ b/Projects/CykaOfQud/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("CykaOfQud")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CykaOfQud")] +[assembly: AssemblyCopyright("Copyright © 2023")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("EE5EFB7F-A4DC-44F0-967B-F71ECA2D46AE")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Projects/CykaOfQud/sync b/Projects/CykaOfQud/sync new file mode 100644 index 0000000..55d037e --- /dev/null +++ b/Projects/CykaOfQud/sync @@ -0,0 +1 @@ +bin/Release/CykaOfQud.dll,"C:/Games/Caves.of.Qud.Build.16668101/BepInEx/plugins/CykaOfQud.dll" \ No newline at end of file