From 67f739bf8e7229f34aa3e2be1e5482cebb4d842b Mon Sep 17 00:00:00 2001 From: Matt Semar Date: Wed, 19 Jan 2022 18:56:19 -0600 Subject: [PATCH 01/16] Update BetterStats build to load dependencies from NuGet and not require copying in files from the game directory --- .gitignore | 6 ++ BetterStats/BetterStats.cs | 3 +- BetterStats/BetterStats.csproj | 139 +++++-------------------- BetterStats/NuGet.Config | 6 ++ BetterStats/Properties/AssemblyInfo.cs | 32 ------ BetterStats/README.md | 8 +- BetterStats/package.ps1 | 71 +++++++++++++ 7 files changed, 114 insertions(+), 151 deletions(-) create mode 100644 BetterStats/NuGet.Config delete mode 100644 BetterStats/Properties/AssemblyInfo.cs create mode 100644 BetterStats/package.ps1 diff --git a/.gitignore b/.gitignore index d92e57b..7d8e1a0 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,12 @@ !.editorconfig !.gitignore !*.md +!*.ps1 +!*.psm1 +!NuGet.Config bin/ obj/ +tmp_release +.idea +.vs diff --git a/BetterStats/BetterStats.cs b/BetterStats/BetterStats.cs index 9f75253..557a593 100644 --- a/BetterStats/BetterStats.cs +++ b/BetterStats/BetterStats.cs @@ -9,8 +9,7 @@ namespace BetterStats { - // TODO: button to next producer/consumer - [BepInPlugin("com.brokenmass.plugin.DSP.BetterStats", "BetterStats", "1.3.2")] + [BepInPlugin("com.brokenmass.plugin.DSP.BetterStats", PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)] public class BetterStats : BaseUnityPlugin { public class EnhancedUIProductEntryElements diff --git a/BetterStats/BetterStats.csproj b/BetterStats/BetterStats.csproj index 23399cf..2be1f07 100644 --- a/BetterStats/BetterStats.csproj +++ b/BetterStats/BetterStats.csproj @@ -1,114 +1,25 @@ - - - - - Debug - AnyCPU - {F415C8D1-768D-407C-86AE-4D2EEAC179F1} - Library - DSM.BetterStats - BetterStats - v4.0 - 512 - true - true - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.2.0 - false - false - true - - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - False - Microsoft .NET Framework 4.8 %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 - false - - - - - C:\Program Files (x86)\Steam\steamapps\common\Dyson Sphere Program\BepInEx\core\0Harmony.dll - - - False - C:\Program Files (x86)\Steam\steamapps\common\Dyson Sphere Program\DSPGAME_Data\Managed\publicized_assemblies\Assembly-CSharp_publicized.dll - - - C:\Program Files (x86)\Steam\steamapps\common\Dyson Sphere Program\BepInEx\core\BepInEx.dll - - - C:\Program Files (x86)\Steam\steamapps\common\Dyson Sphere Program\BepInEx\core\BepInEx.Harmony.dll - - - C:\Program Files (x86)\Steam\steamapps\common\Dyson Sphere Program\BepInEx\core\Mono.Cecil.dll - - - C:\Program Files (x86)\Steam\steamapps\common\Dyson Sphere Program\DSPGAME_Data\Managed\netstandard.dll - - - C:\Program Files (x86)\Steam\steamapps\common\Dyson Sphere Program\BepInEx\DowngradedAssemblies\UnityEngine.dll - - - C:\Program Files (x86)\Steam\steamapps\common\Dyson Sphere Program\DSPGAME_Data\Managed\UnityEngine.CoreModule.dll - - - C:\Program Files (x86)\Steam\steamapps\common\Dyson Sphere Program\DSPGAME_Data\Managed\UnityEngine.JSONSerializeModule.dll - - - C:\Program Files (x86)\Steam\steamapps\common\Dyson Sphere Program\DSPGAME_Data\Managed\UnityEngine.TextRenderingModule.dll - - - C:\Program Files (x86)\Steam\steamapps\common\Dyson Sphere Program\DSPGAME_Data\Managed\UnityEngine.UI.dll - - - C:\Program Files (x86)\Steam\steamapps\common\Dyson Sphere Program\DSPGAME_Data\Managed\UnityEngine.UIModule.dll - - - - - copy $(TargetPath) "C:\Program Files (x86)\Steam\steamapps\common\Dyson Sphere Program\BepInEx\scripts\$(TargetFileName)" - - + + + netstandard2.0 + Add more information to the production stats panel + BetterStats + true + 1.3.3 + + + + + + + + + + + + + + + + + + diff --git a/BetterStats/NuGet.Config b/BetterStats/NuGet.Config new file mode 100644 index 0000000..1864ded --- /dev/null +++ b/BetterStats/NuGet.Config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/BetterStats/Properties/AssemblyInfo.cs b/BetterStats/Properties/AssemblyInfo.cs deleted file mode 100644 index 7f0380c..0000000 --- a/BetterStats/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -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("BetterStats DSP Plugin")] -[assembly: AssemblyDescription("BetterStats DSP Plugin")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("DSM.BetterStats.Properties")] -[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("b339b5f8-5f4e-4671-b752-bfdae0b26a08")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -[assembly: AssemblyVersion("1.3.3")] -[assembly: AssemblyFileVersion("1.3.3")] diff --git a/BetterStats/README.md b/BetterStats/README.md index e0faa10..88a72b0 100644 --- a/BetterStats/README.md +++ b/BetterStats/README.md @@ -62,13 +62,15 @@ Inspired by https://docs.bepinex.dev/master/articles/dev_guide/plugin_tutorial/1 ### Setup visual studio - Install Visual Studio (not visual studio code) -- In Visual Studio, create a new blank project and there choose "add more tools" and add .Net developpement support +- In Visual Studio, create a new blank project and there choose "add more tools" and add .Net development support - Install .Net Framework 3.5 (be careful to choose "Framework") ### project setup - In Visual Studio, choose import and then select "BetterStats.csproj" -- In the right tree, right click references and then select "add references" and add the requered references (most of them located in C:\Program Files (x86)\Steam\steamapps\common\Dyson Sphere Program\DSPGAME_Data\Managed ; others are from BepinEx) -- You will find the last DLL "Assembly-CSharp.refstub.dll" in https://discord.com/channels/806549677209944084/806556447885623336/809241758323572766 +- Game libraries should be loaded from NuGet +### Create a release +- From a PowerShell prompt run `.\package -vertype ` with either major, minor, patch or 'none'. 'none' will not increment the version number +- Uploadable zip file will be placed in .\tmp_release
Icon made by Freepik from www.flaticon.com
diff --git a/BetterStats/package.ps1 b/BetterStats/package.ps1 new file mode 100644 index 0000000..239e413 --- /dev/null +++ b/BetterStats/package.ps1 @@ -0,0 +1,71 @@ +param ($vertype = 'patch') + +Set-StrictMode -Version Latest + +write-host "version type $vertype" + +Remove-Item .\tmp_release -Force -Recurse +New-Item .\tmp_release -ItemType "directory" -Force + +$manifestContent = Get-Content -path .\manifest.json -Raw +$j = $manifestContent | ConvertFrom-Json + +$sourceFileContent = Get-Content -path .\BetterStats.csproj -Raw +$sourceFileContent -match '.*(\d+.\d+.\d+).*' + +$old_vernum = $Matches[1] + +$v = [version]$old_vernum +write-host "v = $v" + +if ($vertype -eq "minor") +{ + $new_version = [version]::New($v.Major, $v.Minor + 1, 0) +} +elseif ($vertype -eq "patch") +{ + $new_version = [version]::New($v.Major, $v.Minor, $v.Build + 1) +} +elseif ($vertype -eq "major") +{ + $new_version = [version]::New($v.Major + 1, 0, 0) +} +elseif ($vertype -eq "none") +{ + $new_version = [version]::New($v.Major, $v.Minor, $v.Build) +} +else +{ + Write-Host "invalid vertype: should be (major, minor, patch), got $vertype" + exit +} + +Write-Host "next version $new_version" +$new_version_string = "$([string]::Join(".", $new_version))"; + +$sourceFileContent -replace $old_vernum, $new_version_string | Set-Content -Path .\BetterStats.csproj -NoNewline + +Start-Process dotnet.exe -ArgumentList "build" -NoNewWindow -PassThru -Wait + +Copy-Item -Path bin/Debug/netstandard2.0/BetterStats.dll -Destination tmp_release +Copy-Item README.md -Destination tmp_release\README.md +Copy-Item icon.png -Destination tmp_release + +if ($vertype -ne "none") +{ + $j.version_number = $new_version_string + $j |ConvertTo-Json | Set-Content -Path .\tmp_release\manifest.json + Copy-Item .\tmp_release\manifest.json manifest.json +} else +{ + Copy-Item .\manifest.json .\tmp_release\manifest.json +} + + +$compress = @{ + Path = "tmp_release\*" + CompressionLevel = "Fastest" + DestinationPath = "tmp_release\BetterStats.zip" +} +Compress-Archive @compress + From 7d167cd2128b0568434d95ffb7fe810372541616 Mon Sep 17 00:00:00 2001 From: Matt Semar Date: Sun, 23 Jan 2022 11:59:37 -0600 Subject: [PATCH 02/16] Fix theoretical max production for advanced miners --- BetterStats/BetterStats.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/BetterStats/BetterStats.cs b/BetterStats/BetterStats.cs index 557a593..cb45f87 100644 --- a/BetterStats/BetterStats.cs +++ b/BetterStats/BetterStats.cs @@ -649,11 +649,21 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) { production = frequency * speed * (float)((double)veinPool[veinId].amount * (double)VeinData.oilSpeedMultiplier); } + + // flag to tell us if it's one of the advanced miners they added in the 20-Jan-2022 release + var isAdvancedMiner = false; if (factorySystem.minerPool[i].type == EMinerType.Vein) { production = frequency * speed * miner.veinCount; + var minerEntity = factorySystem.factory.entityPool[miner.entityId]; + isAdvancedMiner = minerEntity.stationId > 0 && minerEntity.minerId > 0; + } + + // advanced miners aren't limited by belts + if (!isAdvancedMiner) + { + production = Math.Min(BELT_MAX_ITEMS_PER_MINUTE, production); } - production = Math.Min(BELT_MAX_ITEMS_PER_MINUTE, production); counter[productId].production += production; counter[productId].producers++; From 07ccaee62e26b0589a7e3de2478693c69c79aab7 Mon Sep 17 00:00:00 2001 From: Matt Semar Date: Sun, 23 Jan 2022 15:36:42 -0600 Subject: [PATCH 03/16] Add adjustment for assemblers that have the speed toggle enabled --- BetterStats/BetterStats.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BetterStats/BetterStats.cs b/BetterStats/BetterStats.cs index cb45f87..60279c7 100644 --- a/BetterStats/BetterStats.cs +++ b/BetterStats/BetterStats.cs @@ -674,7 +674,7 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) if (assembler.id != i || assembler.recipeId == 0) continue; var frequency = 60f / (float)((double)assembler.timeSpend / 600000.0); - var speed = (float)(0.0001 * (double)assembler.speed); + var speed = (float)(0.0001 * Math.Max(assembler.speedOverride, assembler.speed)); for (int j = 0; j < assembler.requires.Length; j++) { From 6da0bf484be9ee55ddc8d664bfbf1094f7cc9982 Mon Sep 17 00:00:00 2001 From: Matt Semar Date: Sun, 23 Jan 2022 18:07:15 -0600 Subject: [PATCH 04/16] Add adjustment for assemblers with Extra Products toggled --- BetterStats/BetterStats.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/BetterStats/BetterStats.cs b/BetterStats/BetterStats.cs index 60279c7..f82df04 100644 --- a/BetterStats/BetterStats.cs +++ b/BetterStats/BetterStats.cs @@ -675,6 +675,11 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) var frequency = 60f / (float)((double)assembler.timeSpend / 600000.0); var speed = (float)(0.0001 * Math.Max(assembler.speedOverride, assembler.speed)); + // forceAccMode is true when Production Speedup is selected + if (!assembler.forceAccMode) + { + frequency += 60f / (float)( assembler.extraTimeSpend / 600000.0); + } for (int j = 0; j < assembler.requires.Length; j++) { @@ -742,7 +747,7 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) { var lab = factorySystem.labPool[i]; if (lab.id != i) continue; - float frequency = 60f / (float)((double)lab.timeSpend / 600000.0); + float frequency = 60f / (float)(lab.timeSpend / 600000.0); if (lab.matrixMode) { From 5c5bd934e1a1921831869f8ceea48d0eab75b56e Mon Sep 17 00:00:00 2001 From: Matt Semar Date: Sun, 23 Jan 2022 20:03:18 -0600 Subject: [PATCH 05/16] Update lab theoretical max calculations to incorporate speed into equation and to account for labs in extra products mode --- BetterStats/BetterStats.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/BetterStats/BetterStats.cs b/BetterStats/BetterStats.cs index f82df04..fcdd525 100644 --- a/BetterStats/BetterStats.cs +++ b/BetterStats/BetterStats.cs @@ -747,7 +747,15 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) { var lab = factorySystem.labPool[i]; if (lab.id != i) continue; - float frequency = 60f / (float)(lab.timeSpend / 600000.0); + // lab timeSpend is in game ticks, here we are figuring out the same number shown in lab window, example: 2.5 / m + // when we are in Production Speedup mode `speedOverride` is juiced. Otherwise we need to bump the frequency to account + // for the extra product produced after `extraTimeSpend` game ticks + float frequency = (float)(1f / (lab.timeSpend / GameMain.tickPerSec / (60f * Math.Max(lab.speed, lab.speedOverride)))); + + if (!lab.forceAccMode && lab.extraTimeSpend > 0 && lab.extraSpeed > 0) + { + frequency += (float)(1f / (lab.extraTimeSpend / GameMain.tickPerSec / (60f * lab.extraSpeed))); + } if (lab.matrixMode) { From 4da7f8a000bd7ef9a46d11eb1600c5e575923c20 Mon Sep 17 00:00:00 2001 From: Matt Semar Date: Wed, 2 Feb 2022 00:23:14 -0600 Subject: [PATCH 06/16] Update max speed calculations for labs and assemblers to use highest level of proliferator unlocked instead of observed amounts --- BetterStats/BetterStats.cs | 24 +++++++---- BetterStats/ResearchTechHelper.cs | 66 +++++++++++++++++++++++++++++++ BetterStats/package.ps1 | 2 +- 3 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 BetterStats/ResearchTechHelper.cs diff --git a/BetterStats/BetterStats.cs b/BetterStats/BetterStats.cs index fcdd525..7bf9772 100644 --- a/BetterStats/BetterStats.cs +++ b/BetterStats/BetterStats.cs @@ -6,6 +6,8 @@ using UnityEngine; using UnityEngine.UI; using System.Globalization; +using System.Linq; +using DefaultNamespace; namespace BetterStats { @@ -513,8 +515,8 @@ public static void UIProductEntry__OnUpdate_Postfix(UIProductEntry __instance) if (!isTotalTimeWindow) { - originalProductValue = originalProductValue / divider; - originalConsumeValue = originalConsumeValue / divider; + originalProductValue /= divider; + originalConsumeValue /= divider; originalProductText = $"{FormatMetric(originalProductValue)}"; @@ -614,6 +616,8 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) var transport = planetFactory.transport; var veinPool = planetFactory.planet.factory.veinPool; var miningSpeedScale = (double)GameMain.history.miningSpeedScale; + var maxProductivityIncrease = ResearchTechHelper.GetMaxProductivityIncrease(); + var maxSpeedIncrease = ResearchTechHelper.GetMaxSpeedIncrease(); for (int i = 1; i < factorySystem.minerCursor; i++) { @@ -675,10 +679,15 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) var frequency = 60f / (float)((double)assembler.timeSpend / 600000.0); var speed = (float)(0.0001 * Math.Max(assembler.speedOverride, assembler.speed)); + // forceAccMode is true when Production Speedup is selected - if (!assembler.forceAccMode) + if (assembler.forceAccMode) + { + speed += speed * maxSpeedIncrease; + } + else { - frequency += 60f / (float)( assembler.extraTimeSpend / 600000.0); + frequency += frequency * maxProductivityIncrease; } for (int j = 0; j < assembler.requires.Length; j++) @@ -750,11 +759,12 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) // lab timeSpend is in game ticks, here we are figuring out the same number shown in lab window, example: 2.5 / m // when we are in Production Speedup mode `speedOverride` is juiced. Otherwise we need to bump the frequency to account // for the extra product produced after `extraTimeSpend` game ticks - float frequency = (float)(1f / (lab.timeSpend / GameMain.tickPerSec / (60f * Math.Max(lab.speed, lab.speedOverride)))); + var labSpeed = lab.forceAccMode ? (int)(lab.speed * (1.0 + maxSpeedIncrease) + 0.1) : lab.speed; + float frequency = (float)(1f / (lab.timeSpend / GameMain.tickPerSec / (60f * labSpeed))); - if (!lab.forceAccMode && lab.extraTimeSpend > 0 && lab.extraSpeed > 0) + if (!lab.forceAccMode) { - frequency += (float)(1f / (lab.extraTimeSpend / GameMain.tickPerSec / (60f * lab.extraSpeed))); + frequency += frequency * maxProductivityIncrease; } if (lab.matrixMode) diff --git a/BetterStats/ResearchTechHelper.cs b/BetterStats/ResearchTechHelper.cs new file mode 100644 index 0000000..7a979b8 --- /dev/null +++ b/BetterStats/ResearchTechHelper.cs @@ -0,0 +1,66 @@ +using System; +using System.Linq; + +namespace DefaultNamespace +{ + public static class ResearchTechHelper + { + private static TechProto _sprayLevel3Proto; + private static TechProto _sprayLevel2Proto; + private static TechProto _sprayLevel1Proto; + + public static float GetMaxProductivityIncrease() + { + var highestProliferatorTechUnlocked = GetMaxIncIndex(); + return (float)Cargo.incTableMilli[highestProliferatorTechUnlocked]; + } + + public static float GetMaxSpeedIncrease() + { + var highestProliferatorTechUnlocked = GetMaxIncIndex(); + return (float)Cargo.accTableMilli[highestProliferatorTechUnlocked]; + } + + private static int GetMaxIncIndex() + { + InitTechProtos(); + if (GameMain.history.techStates[_sprayLevel3Proto.ID].unlocked) + return 4; + if (GameMain.history.techStates[_sprayLevel2Proto.ID].unlocked) + return 2; + if (GameMain.history.techStates[_sprayLevel1Proto.ID].unlocked) + return 1; + return 0; + } + + private static void InitTechProtos() + { + if (_sprayLevel3Proto == null) + { + var proliferatorProtos = LDB.techs.dataArray.ToList().FindAll(t => t.Name.Contains("增产剂")); + proliferatorProtos.Sort((p1, p2) => + { + if (p1.PreTechs.Contains(p2.ID)) + { + // sorting high to low + return -1; + } + + if (p2.PreTechs.Contains(p1.ID)) + { + return 1; + } + + return p1.ID.CompareTo(p2.ID); + }); + if (proliferatorProtos.Count >= 3) + { + // if more are added, add them here + _sprayLevel3Proto = proliferatorProtos[0]; + _sprayLevel2Proto = proliferatorProtos[1]; + _sprayLevel1Proto = proliferatorProtos[2]; + } + } + } + } +} diff --git a/BetterStats/package.ps1 b/BetterStats/package.ps1 index 239e413..130830f 100644 --- a/BetterStats/package.ps1 +++ b/BetterStats/package.ps1 @@ -45,7 +45,7 @@ $new_version_string = "$([string]::Join(".", $new_version))"; $sourceFileContent -replace $old_vernum, $new_version_string | Set-Content -Path .\BetterStats.csproj -NoNewline -Start-Process dotnet.exe -ArgumentList "build" -NoNewWindow -PassThru -Wait +Start-Process dotnet.exe -ArgumentList "build" -NoNewWindow -Wait Copy-Item -Path bin/Debug/netstandard2.0/BetterStats.dll -Destination tmp_release Copy-Item README.md -Destination tmp_release\README.md From 70932baabe45e70838e6b268bdb91a216453e43c Mon Sep 17 00:00:00 2001 From: Matt Semar Date: Wed, 2 Feb 2022 17:31:28 -0600 Subject: [PATCH 07/16] Update to apply productivity bonus only to production --- BetterStats/BetterStats.cs | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/BetterStats/BetterStats.cs b/BetterStats/BetterStats.cs index 7bf9772..c0d1e1d 100644 --- a/BetterStats/BetterStats.cs +++ b/BetterStats/BetterStats.cs @@ -677,17 +677,18 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) var assembler = factorySystem.assemblerPool[i]; if (assembler.id != i || assembler.recipeId == 0) continue; - var frequency = 60f / (float)((double)assembler.timeSpend / 600000.0); + var baseFrequency = 60f / (float)(assembler.timeSpend / 600000.0); + var productionFrequency = baseFrequency; var speed = (float)(0.0001 * Math.Max(assembler.speedOverride, assembler.speed)); - // forceAccMode is true when Production Speedup is selected + // forceAccMode is 'Production Speedup' mode. It just adds a straight increase to both production and consumption rate if (assembler.forceAccMode) { speed += speed * maxSpeedIncrease; } else { - frequency += frequency * maxProductivityIncrease; + productionFrequency += productionFrequency * maxProductivityIncrease; } for (int j = 0; j < assembler.requires.Length; j++) @@ -695,7 +696,7 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) var productId = assembler.requires[j]; EnsureId(ref counter, productId); - counter[productId].consumption += frequency * speed * assembler.requireCounts[j]; + counter[productId].consumption += baseFrequency * speed * assembler.requireCounts[j]; counter[productId].consumers++; } @@ -704,7 +705,7 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) var productId = assembler.products[j]; EnsureId(ref counter, productId); - counter[productId].production += frequency * speed * assembler.productCounts[j]; + counter[productId].production += productionFrequency * speed * assembler.productCounts[j]; counter[productId].producers++; } } @@ -757,14 +758,15 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) var lab = factorySystem.labPool[i]; if (lab.id != i) continue; // lab timeSpend is in game ticks, here we are figuring out the same number shown in lab window, example: 2.5 / m - // when we are in Production Speedup mode `speedOverride` is juiced. Otherwise we need to bump the frequency to account - // for the extra product produced after `extraTimeSpend` game ticks + // when we are in Production Speedup mode `speedOverride` is increased. var labSpeed = lab.forceAccMode ? (int)(lab.speed * (1.0 + maxSpeedIncrease) + 0.1) : lab.speed; - float frequency = (float)(1f / (lab.timeSpend / GameMain.tickPerSec / (60f * labSpeed))); + float baseFrequency = (float)(1f / (lab.timeSpend / GameMain.tickPerSec / (60f * labSpeed))); + float productionFrequency = baseFrequency; if (!lab.forceAccMode) { - frequency += frequency * maxProductivityIncrease; + // productivity bonuses are in Cargo table in the incTableMilli array + productionFrequency += baseFrequency * maxProductivityIncrease; } if (lab.matrixMode) @@ -774,7 +776,7 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) var productId = lab.requires[j]; EnsureId(ref counter, productId); - counter[productId].consumption += frequency * lab.requireCounts[j]; + counter[productId].consumption += baseFrequency * lab.requireCounts[j]; counter[productId].consumers++; } @@ -783,7 +785,7 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) var productId = lab.products[j]; EnsureId(ref counter, productId); - counter[productId].production += frequency * lab.productCounts[j]; + counter[productId].production += productionFrequency * lab.productCounts[j]; counter[productId].producers++; } } From 2509e7d4ba27cd4db0253bfda6395c5ae00504ab Mon Sep 17 00:00:00 2001 From: Matt Semar Date: Wed, 2 Feb 2022 17:34:19 -0600 Subject: [PATCH 08/16] revert change to base assembler speed calculation --- BetterStats/BetterStats.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BetterStats/BetterStats.cs b/BetterStats/BetterStats.cs index c0d1e1d..f93e0ca 100644 --- a/BetterStats/BetterStats.cs +++ b/BetterStats/BetterStats.cs @@ -679,7 +679,7 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) var baseFrequency = 60f / (float)(assembler.timeSpend / 600000.0); var productionFrequency = baseFrequency; - var speed = (float)(0.0001 * Math.Max(assembler.speedOverride, assembler.speed)); + var speed = (float)(0.0001 * (double)assembler.speed); // forceAccMode is 'Production Speedup' mode. It just adds a straight increase to both production and consumption rate if (assembler.forceAccMode) From c10a8f8274be2967485e456aa6a8d229d4a6062a Mon Sep 17 00:00:00 2001 From: Matt Semar Date: Thu, 3 Feb 2022 00:31:44 -0600 Subject: [PATCH 09/16] Fix universe matrix max consumption calculation. --- BetterStats/BetterStats.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/BetterStats/BetterStats.cs b/BetterStats/BetterStats.cs index f93e0ca..c2e537a 100644 --- a/BetterStats/BetterStats.cs +++ b/BetterStats/BetterStats.cs @@ -6,7 +6,6 @@ using UnityEngine; using UnityEngine.UI; using System.Globalization; -using System.Linq; using DefaultNamespace; namespace BetterStats @@ -569,7 +568,7 @@ public static void UIProductEntry__OnUpdate_Postfix(UIProductEntry __instance) [HarmonyPrefix, HarmonyPatch(typeof(UIStatisticsWindow), "ComputeDisplayEntries")] public static void UIProductionStatWindow_ComputeDisplayEntries_Prefix(UIStatisticsWindow __instance) { - if (Time.frameCount % 10 != 0) + if (Time.frameCount % 10 != 0 && lastStatTimer == __instance.timeLevel) { return; } @@ -797,13 +796,13 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) if (techProto == null) continue; TechState techState = GameMain.history.TechState(techProto.ID); + float hashPerMinute = (float)(60.0f * (GameMain.data.history.techSpeed * (1.0 + (double) maxProductivityIncrease / 6.0f))); + for (int index = 0; index < techProto.itemArray.Length; ++index) { var item = techProto.Items[index]; - var cubesNeeded = techProto.GetHashNeeded(techState.curLevel) * techProto.ItemPoints[index] / 3600L; - var researchRate = GameMain.history.techSpeed * 60.0f; - var hashesPerCube = (float) techState.hashNeeded / cubesNeeded; - var researchFreq = hashesPerCube / researchRate; + var researchRateSec = (float) GameMain.history.techSpeed * GameMain.tickPerSec; + var researchFreq = (float) (techState.uPointPerHash * hashPerMinute / researchRateSec); EnsureId(ref counter, item); counter[item].consumers++; counter[item].consumption += researchFreq * GameMain.history.techSpeed; From 7928dbe927b9b0a1511294750788ad13b2aeca40 Mon Sep 17 00:00:00 2001 From: Matt Semar Date: Fri, 4 Feb 2022 17:40:21 -0600 Subject: [PATCH 10/16] First pass on buttons added to control the different calculation modes --- BetterStats/BetterStats.cs | 111 ++++-- BetterStats/BetterStats.csproj | 1 + BetterStats/ItemCalculationMode.cs | 147 ++++++++ BetterStats/ProliferatorOperationSetting.cs | 361 ++++++++++++++++++++ BetterStats/ResearchTechHelper.cs | 3 +- BetterStats/package.ps1 | 2 +- 6 files changed, 601 insertions(+), 24 deletions(-) create mode 100644 BetterStats/ItemCalculationMode.cs create mode 100644 BetterStats/ProliferatorOperationSetting.cs diff --git a/BetterStats/BetterStats.cs b/BetterStats/BetterStats.cs index c2e537a..454640c 100644 --- a/BetterStats/BetterStats.cs +++ b/BetterStats/BetterStats.cs @@ -6,6 +6,7 @@ using UnityEngine; using UnityEngine.UI; using System.Globalization; +using BepInEx.Logging; using DefaultNamespace; namespace BetterStats @@ -28,12 +29,14 @@ public class EnhancedUIProductEntryElements public Text counterConsumptionLabel; public Text counterConsumptionValue; + public ProliferatorOperationSetting proliferatorOperationSetting; } + Harmony harmony; private static ConfigEntry lackOfProductionRatioTrigger; private static ConfigEntry consumptionToProductionRatioTrigger; private static ConfigEntry displayPerSecond; - private static Dictionary counter = new Dictionary(); + private static Dictionary counter = new(); private static GameObject txtGO, chxGO, filterGO; private static Texture2D texOff = Resources.Load("ui/textures/sprites/icons/checkbox-off"); private static Texture2D texOn = Resources.Load("ui/textures/sprites/icons/checkbox-on"); @@ -54,19 +57,24 @@ public class EnhancedUIProductEntryElements private static Dictionary enhancements = new Dictionary(); private static UIStatisticsWindow statWindow; + public static ManualLogSource Log; internal void Awake() { + Log = Logger; InitConfig(); harmony = new Harmony("com.brokenmass.plugin.DSP.BetterStats"); try { harmony.PatchAll(typeof(BetterStats)); + harmony.PatchAll(typeof(ItemCalculationRuntimeSetting)); + ProliferatorOperationSetting.Init(); } catch (Exception e) { - Console.WriteLine(e.ToString()); + Log.LogWarning(e.ToString()); } + Log.LogInfo($"{PluginInfo.PLUGIN_NAME} {PluginInfo.PLUGIN_VERSION} Loaded"); } internal void InitConfig() @@ -99,6 +107,7 @@ internal void OnDestroy() } ClearEnhancedUIProductEntries(); + ProliferatorOperationSetting.Unload(); harmony.UnpatchSelf(); } @@ -155,7 +164,6 @@ private static void EnsureId(ref Dictionary dict, int id) if (!dict.ContainsKey(id)) { ItemProto itemProto = LDB.items.Select(id); - dict.Add(id, new ProductMetrics() { itemProto = itemProto @@ -301,7 +309,7 @@ private static EnhancedUIProductEntryElements EnhanceUIProductEntry(UIProductEnt var counterConsumptionValue = CopyText(__instance.consumeText, new Vector2(-initialXOffset, 0)); counterConsumptionValue.GetComponent().sizeDelta = new Vector2(60, 40); counterConsumptionValue.text = "0"; - + var proliferatorOpSetting = ProliferatorOperationSetting.ForProductEntry(__instance); var enhancement = new EnhancedUIProductEntryElements { maxProductionLabel = maxProductionLabel, @@ -317,6 +325,7 @@ private static EnhancedUIProductEntryElements EnhanceUIProductEntry(UIProductEnt counterConsumptionLabel = counterConsumptionLabel, counterConsumptionValue = counterConsumptionValue, + proliferatorOperationSetting = proliferatorOpSetting }; enhancements.Add(__instance, enhancement); @@ -563,6 +572,7 @@ public static void UIProductEntry__OnUpdate_Postfix(UIProductEntry __instance) if (warnOnHighMaxConsumption && !isTotalTimeWindow) enhancement.maxConsumptionValue.color = new Color(1f, 1f, .25f, .5f); + enhancement.proliferatorOperationSetting.UpdateItemId(__instance.entryData.itemId); } [HarmonyPrefix, HarmonyPatch(typeof(UIStatisticsWindow), "ComputeDisplayEntries")] @@ -680,14 +690,35 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) var productionFrequency = baseFrequency; var speed = (float)(0.0001 * (double)assembler.speed); + ItemCalculationRuntimeSetting runtimeSetting = ProliferatorOperationSetting.ForRecipe(assembler.recipeId); + // forceAccMode is 'Production Speedup' mode. It just adds a straight increase to both production and consumption rate - if (assembler.forceAccMode) - { - speed += speed * maxSpeedIncrease; - } - else + if (runtimeSetting.Enabled) { - productionFrequency += productionFrequency * maxProductivityIncrease; + if (runtimeSetting.Mode == ItemCalculationMode.Normal) + { + // let assembler decide + if (assembler.forceAccMode) + { + speed += speed * maxSpeedIncrease; + } + else + { + productionFrequency += productionFrequency * maxProductivityIncrease; + } + } + else if (runtimeSetting.Mode == ItemCalculationMode.ForceSpeed) + { + speed += speed * maxSpeedIncrease; + } + else if (runtimeSetting.Mode == ItemCalculationMode.ForceProductivity) + { + productionFrequency += productionFrequency * maxProductivityIncrease; + } + else + { + Log.LogWarning($"unexpected runtime setting ${JsonUtility.ToJson(runtimeSetting)}"); + } } for (int j = 0; j < assembler.requires.Length; j++) @@ -756,17 +787,7 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) { var lab = factorySystem.labPool[i]; if (lab.id != i) continue; - // lab timeSpend is in game ticks, here we are figuring out the same number shown in lab window, example: 2.5 / m - // when we are in Production Speedup mode `speedOverride` is increased. - var labSpeed = lab.forceAccMode ? (int)(lab.speed * (1.0 + maxSpeedIncrease) + 0.1) : lab.speed; - float baseFrequency = (float)(1f / (lab.timeSpend / GameMain.tickPerSec / (60f * labSpeed))); - float productionFrequency = baseFrequency; - - if (!lab.forceAccMode) - { - // productivity bonuses are in Cargo table in the incTableMilli array - productionFrequency += baseFrequency * maxProductivityIncrease; - } + (float baseFrequency, float productionFrequency) = DetermineLabFrequencies(ref lab, maxProductivityIncrease, maxSpeedIncrease); if (lab.matrixMode) { @@ -866,5 +887,53 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) } } } + + private static (float, float) DetermineLabFrequencies(ref LabComponent lab, float maxProductivityIncrease, float maxSpeedIncrease) + { + // lab timeSpend is in game ticks, here we are figuring out the same number shown in lab window, example: 2.5 / m + // when we are in Production Speedup mode `speedOverride` is increased. + float baseFrequency = 0f, productionFrequency = 0; + + var runtimeSetting = ProliferatorOperationSetting.ForRecipe(lab.recipeId); + + if (runtimeSetting != null && runtimeSetting.Enabled) + { + if (runtimeSetting.Mode == ItemCalculationMode.Normal) + { + // use whatever setting the lab has decide + if (!lab.forceAccMode) + { + // productivity bonuses are in Cargo table in the incTableMilli array + baseFrequency = (float)(1f / (lab.timeSpend / GameMain.tickPerSec / (60f * lab.speed))); + productionFrequency = baseFrequency + baseFrequency * maxProductivityIncrease; + } + else + { + var labSpeed = lab.speed * (1.0 + maxSpeedIncrease) + 0.1; + baseFrequency = (float)(1f / (lab.timeSpend / GameMain.tickPerSec / (60f * labSpeed))); + productionFrequency = baseFrequency; + } + } + else if (runtimeSetting.Mode == ItemCalculationMode.ForceSpeed) + { + var labSpeed = lab.speed * (1.0 + maxSpeedIncrease) + 0.1; + baseFrequency = (float)(1f / (lab.timeSpend / GameMain.tickPerSec / (60f * labSpeed))); + productionFrequency = baseFrequency; + } + else if (runtimeSetting.Mode == ItemCalculationMode.ForceProductivity) + { + baseFrequency = (float)(1f / (lab.timeSpend / GameMain.tickPerSec / (60f * lab.speed))); + productionFrequency = baseFrequency + baseFrequency * maxProductivityIncrease; + } + } + else + { + // regular calculation + baseFrequency = (float)(1f / (lab.timeSpend / GameMain.tickPerSec / (60f * lab.speed))); + productionFrequency = baseFrequency; + } + + return (baseFrequency, productionFrequency); + } } } diff --git a/BetterStats/BetterStats.csproj b/BetterStats/BetterStats.csproj index 2be1f07..ee897b6 100644 --- a/BetterStats/BetterStats.csproj +++ b/BetterStats/BetterStats.csproj @@ -5,6 +5,7 @@ BetterStats true 1.3.3 + 9 diff --git a/BetterStats/ItemCalculationMode.cs b/BetterStats/ItemCalculationMode.cs new file mode 100644 index 0000000..c641896 --- /dev/null +++ b/BetterStats/ItemCalculationMode.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using BepInEx; +using BepInEx.Configuration; +using HarmonyLib; +using UnityEngine; +using static BetterStats.BetterStats; + +namespace BetterStats +{ + public enum ItemCalculationMode + { + None, + Normal, + ForceSpeed, + ForceProductivity + } + + /// + /// Manages currently selected proliferator calculation options for each item + /// + public class ItemCalculationRuntimeSetting + { + private ItemCalculationMode _mode = ItemCalculationMode.Normal; + private bool _enabled; + public readonly int productId; + public readonly bool productivitySupported; + public readonly bool speedSupported; + private ConfigEntry _configEntry; + private static readonly Dictionary> ConfigEntries = new(); + private static readonly Dictionary Pool = new(); + private static ConfigFile configFile; + + + private ItemCalculationRuntimeSetting(int productId) + { + this.productId = productId; + var itemProto = LDB.items.Select(productId); + if (itemProto != null) + { + speedSupported = itemProto.recipes is { Count: > 0 }; + productivitySupported = speedSupported && itemProto.recipes.Any(r => r.productive); + _enabled = speedSupported; + } + + if (productivitySupported) + Log.LogDebug($"productivity supported for {itemProto?.name}"); + else + Log.LogDebug($"NO productivity mode supported for {itemProto?.name}"); + } + + public ItemCalculationMode Mode + { + get => _mode; + set + { + _mode = value; + Pool[productId]._mode = value; + Save(); + } + } + + public bool Enabled + { + get => _enabled && speedSupported; + set + { + _enabled = value; + Pool[productId]._enabled = value; + Save(); + } + } + + private void Save() + { + _configEntry.Value = Serialize(); + Log.LogDebug($"saved {productId} entry {_configEntry.Value}"); + } + + private static ItemCalculationRuntimeSetting Deserialize(string strVal) + { + var serializableRuntimeState = JsonUtility.FromJson(strVal); + + return new ItemCalculationRuntimeSetting(serializableRuntimeState.productId) + { + _enabled = serializableRuntimeState.enabled, + _mode = (ItemCalculationMode)serializableRuntimeState.mode, + }; + } + + private string Serialize() + { + return JsonUtility.ToJson(SerializableRuntimeState.From(this)); + } + + private static void InitConfig(ItemProto itemProto) + { + if (configFile == null) + { + configFile = new ConfigFile($"{Paths.ConfigPath}/{PluginInfo.PLUGIN_NAME}/CustomProductSettings.cfg", true); + } + + var defaultValue = new ItemCalculationRuntimeSetting(itemProto.ID); + + var configEntry = configFile.Bind("Internal", $"ProliferatorStatsSetting_{itemProto.ID}", + defaultValue.Serialize(), + "For internal use only"); + ConfigEntries[itemProto.ID] = configEntry; + + Pool[itemProto.ID] = Deserialize(ConfigEntries[itemProto.ID].Value); + Pool[itemProto.ID]._configEntry = configEntry; + Log.LogDebug($"Loaded {itemProto.name} runtime settings"); + } + + public static ItemCalculationRuntimeSetting ForItemId(int itemId) + { + return Pool[itemId]; + } + + [HarmonyPostfix, HarmonyPatch(typeof(ItemProto), nameof(ItemProto.Preload))] + public static void UIStatisticsWindow__OnOpen_Postfix(ItemProto __instance) + { + InitConfig(__instance); + } + } + + [Serializable] + public class SerializableRuntimeState + { + [SerializeField] public int mode; + [SerializeField] public bool enabled; + [SerializeField] public int productId; + + public SerializableRuntimeState(int productId, bool enabled, ItemCalculationMode mode) + { + this.productId = productId; + this.enabled = enabled; + this.mode = (int)mode; + } + + public static SerializableRuntimeState From(ItemCalculationRuntimeSetting setting) + { + return new SerializableRuntimeState(setting.productId, setting.Enabled, setting.Mode); + } + } +} diff --git a/BetterStats/ProliferatorOperationSetting.cs b/BetterStats/ProliferatorOperationSetting.cs new file mode 100644 index 0000000..91d5870 --- /dev/null +++ b/BetterStats/ProliferatorOperationSetting.cs @@ -0,0 +1,361 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; +using static BetterStats.BetterStats; +using static UnityEngine.Object; + +namespace BetterStats +{ + /// + /// Manages operation of proliferator modes + /// + public class ProliferatorOperationSetting + { + private const string PROLIFERATOR_POINT_CALCULATION_DISABLED = "Proliferator Calculation Disabled"; + private const string PROLIFERATOR_POINT_CALCULATION_ENABLE = "Proliferator Calculation Enabled"; + private const string ASSEMBLER_SELECTION_MODE = "Assembler Selection Mode"; + private const string FORCE_PRODUCTIVITY_MODE = "Force Productivity Mode"; + private const string FORCE_SPEED_MODE = "Force Speed Mode"; + + private UIButton _normalOperationButton; + private UIButton _disableButton; + private UIButton _forceSpeedButton; + private UIButton _forceProductivityButton; + private readonly List _availableButtons = new(); + private int _productId; + + private static readonly Dictionary OperationModeSprites = new(); + private static Sprite checkboxOffSprite; + private static Sprite checkboxOnSprite; + private static readonly Dictionary ByProductEntry = new(); + + private ProliferatorOperationSetting() + { + } + + public static void Init() + { + InitSprites(); + } + + + private static void InitSprites() + { + var productivityTexture = Resources.Load("ui/textures/sprites/icons/plus"); + var normalProlifTexture = Resources.Load("ui/textures/sprites/icons/factory-icon"); + var speedTexture = Resources.Load("ui/textures/sprites/sci-fi/arrow-mark-60px"); + var checkBoxOff = Resources.Load("ui/textures/sprites/icons/checkbox-off"); + var checkBoxOn = Resources.Load("ui/textures/sprites/icons/checkbox-on"); + OperationModeSprites[ItemCalculationMode.ForceSpeed] = Sprite.Create(speedTexture, + new Rect(0, 0, speedTexture.width, speedTexture.height), + new Vector2(0.5f, 0.5f)); + + OperationModeSprites[ItemCalculationMode.ForceProductivity] = Sprite.Create(productivityTexture, + new Rect(0, 0, productivityTexture.width, productivityTexture.height), + new Vector2(0.5f, 0.5f)); + + checkboxOnSprite = Sprite.Create(checkBoxOn, + new Rect(0, 0, checkBoxOn.width, checkBoxOn.height), + new Vector2(0.5f, 0.5f)); + checkboxOffSprite = Sprite.Create(checkBoxOff, + new Rect(0, 0, checkBoxOff.width, checkBoxOff.height), + new Vector2(0.5f, 0.5f)); + OperationModeSprites[ItemCalculationMode.Normal] = Sprite.Create(normalProlifTexture, + new Rect(0, 0, normalProlifTexture.width, normalProlifTexture.height), + new Vector2(0.5f, 0.5f)); + } + + public static ProliferatorOperationSetting ForProductEntry(UIProductEntry uiProductEntry) + { + var itemId = uiProductEntry.entryData.itemId; + ProliferatorOperationSetting result; + + if (ByProductEntry.ContainsKey(uiProductEntry)) + { + result = ByProductEntry[uiProductEntry]; + result._productId = uiProductEntry.entryData.itemId; + result.SyncButtons(); + return result; + } + + result = new ProliferatorOperationSetting(); + ByProductEntry[uiProductEntry] = result; + + result._productId = uiProductEntry.entryData.itemId; + + var sourceButton = uiProductEntry.favoriteBtn1; + var xOffset = 80; + + result._disableButton = CopyButton(uiProductEntry, sourceButton, new Vector2(xOffset, 85), + result.OnModeDisable, itemId, checkboxOnSprite, + PROLIFERATOR_POINT_CALCULATION_DISABLED, + "Don't use Proliferator Points for calculation of Theoretical max values"); + result._availableButtons.Add(result._disableButton); + + result._normalOperationButton = CopyButton(uiProductEntry, sourceButton, new Vector2(xOffset, 60), + result.OnNormalClicked, itemId, OperationModeSprites[ItemCalculationMode.Normal], + ASSEMBLER_SELECTION_MODE, + "Max values calculated using currently selected mode for each assembler."); + result._availableButtons.Add(result._normalOperationButton); + + result._forceSpeedButton = CopyButton(uiProductEntry, sourceButton, new Vector2(xOffset, 35), + result.OnForceSpeedClicked, itemId, OperationModeSprites[ItemCalculationMode.ForceSpeed], + FORCE_SPEED_MODE, + "Max values calculated as if all all assemblers were set to 'Production Speedup'."); + result._availableButtons.Add(result._forceSpeedButton); + + result._forceProductivityButton = CopyButton(uiProductEntry, sourceButton, new Vector2(xOffset, 10), + result.OnForceProductivity, itemId, OperationModeSprites[ItemCalculationMode.ForceProductivity], + FORCE_PRODUCTIVITY_MODE, + "Max values calculated as if all all assemblers were set to 'Extra Products'."); + result._availableButtons.Add(result._forceProductivityButton); + result.SyncButtons(); + return result; + } + + private void OnForceProductivity(int itemId) + { + var setting = ItemCalculationRuntimeSetting.ForItemId(_productId); + setting.Enabled = true; + setting.Mode = ItemCalculationMode.ForceProductivity; + SyncButtons(); + } + + private void OnForceSpeedClicked(int itemId) + { + // _productId = itemId; + var setting = ItemCalculationRuntimeSetting.ForItemId(_productId); + setting.Enabled = true; + setting.Mode = ItemCalculationMode.ForceSpeed; + + SyncButtons(); + } + + private void OnNormalClicked(int itemId) + { + var setting = ItemCalculationRuntimeSetting.ForItemId(_productId); + setting.Mode = ItemCalculationMode.Normal; + SyncButtons(); + } + + private void OnModeDisable(int itemId) + { + var setting = ItemCalculationRuntimeSetting.ForItemId(_productId); + Log.LogDebug($"switching item {itemId} to {!setting.Enabled} {setting.productId}"); + setting.Enabled = !setting.Enabled; + if (setting.Enabled && setting.Mode == ItemCalculationMode.None) + { + setting.Mode = ItemCalculationMode.Normal; + } // otherwise we'll just use whatever they had before disabling + + SyncButtons(); + } + + private void SyncButtons() + { + ReInitButtonStates(); + + var runtimeSetting = ItemCalculationRuntimeSetting.ForItemId(_productId); + + if (!runtimeSetting.Enabled) + { + _disableButton.tips.tipTitle = $"{PROLIFERATOR_POINT_CALCULATION_DISABLED}"; + _disableButton.button.image.sprite = checkboxOffSprite; + } + else + { + _disableButton.tips.tipTitle = $"{PROLIFERATOR_POINT_CALCULATION_ENABLE}"; + _disableButton.button.image.sprite = checkboxOnSprite; + } + + foreach (var availableButton in _availableButtons) + { + if (availableButton == _disableButton) + continue; + availableButton.gameObject + .SetActive(availableButton == _forceProductivityButton ? runtimeSetting.productivitySupported : runtimeSetting.Enabled); + } + + switch (runtimeSetting.Mode) + { + case ItemCalculationMode.Normal: + { + _normalOperationButton.tips.tipTitle = $"(current) {ASSEMBLER_SELECTION_MODE}"; + _normalOperationButton.highlighted = true; + break; + } + case ItemCalculationMode.ForceProductivity: + { + _forceProductivityButton.tips.tipTitle = $"(current) {FORCE_PRODUCTIVITY_MODE}"; + _forceProductivityButton.highlighted = true; + break; + } + case ItemCalculationMode.ForceSpeed: + { + _forceSpeedButton.tips.tipTitle = $"(current) {FORCE_SPEED_MODE}"; + _forceSpeedButton.highlighted = true; + break; + } + } + } + + private void ReInitButtonStates() + { + var runtimeSetting = ItemCalculationRuntimeSetting.ForItemId(_productId); + if (!runtimeSetting.speedSupported) + { + foreach (var button in _availableButtons) + { + button.gameObject.SetActive(false); + } + + return; + } + + if (_forceProductivityButton != null) + { + _forceProductivityButton.tips.tipTitle = FORCE_PRODUCTIVITY_MODE; + _forceProductivityButton.highlighted = false; + _forceProductivityButton.button.interactable = true; + _forceProductivityButton.gameObject.SetActive(runtimeSetting.productivitySupported); + } + + if (_forceSpeedButton != null) + { + _forceSpeedButton.tips.tipTitle = FORCE_SPEED_MODE; + _forceSpeedButton.highlighted = false; + _forceSpeedButton.button.interactable = true; + _forceSpeedButton.gameObject.SetActive(true); + } + + if (_disableButton != null) + { + _disableButton.tips.tipTitle = PROLIFERATOR_POINT_CALCULATION_DISABLED; + _disableButton.highlighted = true; + _disableButton.button.interactable = true; + _disableButton.gameObject.SetActive(true); + } + + if (_normalOperationButton != null) + { + _normalOperationButton.tips.tipTitle = ASSEMBLER_SELECTION_MODE; + _normalOperationButton.highlighted = false; + _normalOperationButton.button.interactable = true; + _normalOperationButton.gameObject.SetActive(true); + } + } + + private static UIButton CopyButton(UIProductEntry uiProductEntry, + UIButton button, + Vector2 positionDelta, + Action action, + int productId, + Sprite btnSprite, + string buttonHoverTitle, + string buttonHoverText) + { + var rectTransform = button.GetComponent(); + var copied = Instantiate(rectTransform, uiProductEntry.transform, false); + var copiedImage = copied.transform.GetComponent(); + copiedImage.sprite = btnSprite; + copiedImage.fillAmount = 0; + + copied.anchorMin = rectTransform.anchorMin; + copied.anchorMax = rectTransform.anchorMax; + copied.sizeDelta = rectTransform.sizeDelta * 0.75f; + copied.anchoredPosition = rectTransform.anchoredPosition + positionDelta; + var newActionButton = copied.GetComponentInChildren(); + if (newActionButton != null) + { + newActionButton.tips.tipTitle = buttonHoverTitle; + newActionButton.tips.tipText = buttonHoverText; + newActionButton.button.onClick.RemoveAllListeners(); + newActionButton.button.onClick.AddListener(() => action.Invoke(productId)); + newActionButton.highlighted = false; + newActionButton.Init(); + } + + return newActionButton; + } + + public static void Unload() + { + foreach (var operationModeSprite in OperationModeSprites.Values) + { + Destroy(operationModeSprite); + } + foreach (var setting in ByProductEntry.Values) + { + DestroySetting(setting); + } + } + + private static void DestroySetting(ProliferatorOperationSetting setting) + { + try + { + if (setting._disableButton != null && setting._disableButton.gameObject != null) + { + Destroy(setting._disableButton.gameObject); + } + + if (setting._forceProductivityButton != null && setting._forceProductivityButton.gameObject != null) + { + Destroy(setting._forceProductivityButton.gameObject); + } + + if (setting._normalOperationButton != null && setting._normalOperationButton.gameObject != null) + { + Destroy(setting._normalOperationButton.gameObject); + } + + if (setting._forceSpeedButton != null && setting._forceSpeedButton.gameObject != null) + { + Destroy(setting._forceSpeedButton.gameObject); + } + } + catch (Exception e) + { + Log.LogWarning($"exception while disabling setting: {e.Message}"); + } + } + + public void UpdateItemId(int newItemId) + { + if (_productId == newItemId) + { + // nothing to do + return; + } + + _productId = newItemId; + SyncButtons(); + } + + private static readonly Dictionary _chosenItemIdForRecipeId = new(); + + public static ItemCalculationRuntimeSetting ForRecipe(int assemblerRecipeId) + { + if (_chosenItemIdForRecipeId.TryGetValue(assemblerRecipeId, out var chosenItemId)) + { + return ItemCalculationRuntimeSetting.ForItemId(chosenItemId); + } + + var recipeProto = LDB.recipes.Select(assemblerRecipeId); + if (recipeProto == null) + return null; + chosenItemId = recipeProto.Results[0]; + if (recipeProto.Results.Length == 1) + { + _chosenItemIdForRecipeId[assemblerRecipeId] = chosenItemId; + return ItemCalculationRuntimeSetting.ForItemId(chosenItemId); + } + + // todo figure out better way to manage this + _chosenItemIdForRecipeId[assemblerRecipeId] = chosenItemId; + Log.LogDebug($"chose {chosenItemId} for recipe {recipeProto.name} (total: {recipeProto.Results.Length})"); + return ItemCalculationRuntimeSetting.ForItemId(chosenItemId); + } + } +} diff --git a/BetterStats/ResearchTechHelper.cs b/BetterStats/ResearchTechHelper.cs index 7a979b8..30688d4 100644 --- a/BetterStats/ResearchTechHelper.cs +++ b/BetterStats/ResearchTechHelper.cs @@ -1,5 +1,4 @@ -using System; -using System.Linq; +using System.Linq; namespace DefaultNamespace { diff --git a/BetterStats/package.ps1 b/BetterStats/package.ps1 index 130830f..348b5fe 100644 --- a/BetterStats/package.ps1 +++ b/BetterStats/package.ps1 @@ -45,7 +45,7 @@ $new_version_string = "$([string]::Join(".", $new_version))"; $sourceFileContent -replace $old_vernum, $new_version_string | Set-Content -Path .\BetterStats.csproj -NoNewline -Start-Process dotnet.exe -ArgumentList "build" -NoNewWindow -Wait +Start-Process dotnet.exe -ArgumentList "build" -Wait Copy-Item -Path bin/Debug/netstandard2.0/BetterStats.dll -Destination tmp_release Copy-Item README.md -Destination tmp_release\README.md From 9880e0c08fad971956b2ea17e3876fcd444643d4 Mon Sep 17 00:00:00 2001 From: Matt Semar Date: Sat, 5 Feb 2022 17:24:28 -0600 Subject: [PATCH 11/16] Fixed items allowing force productivity mode --- BetterStats/BetterStats.cs | 1 - BetterStats/ItemCalculationMode.cs | 68 ++++++++++----------- BetterStats/ProliferatorOperationSetting.cs | 29 ++++++--- 3 files changed, 51 insertions(+), 47 deletions(-) diff --git a/BetterStats/BetterStats.cs b/BetterStats/BetterStats.cs index 454640c..52f056d 100644 --- a/BetterStats/BetterStats.cs +++ b/BetterStats/BetterStats.cs @@ -67,7 +67,6 @@ internal void Awake() try { harmony.PatchAll(typeof(BetterStats)); - harmony.PatchAll(typeof(ItemCalculationRuntimeSetting)); ProliferatorOperationSetting.Init(); } catch (Exception e) diff --git a/BetterStats/ItemCalculationMode.cs b/BetterStats/ItemCalculationMode.cs index c641896..01ca0a5 100644 --- a/BetterStats/ItemCalculationMode.cs +++ b/BetterStats/ItemCalculationMode.cs @@ -3,7 +3,6 @@ using System.Linq; using BepInEx; using BepInEx.Configuration; -using HarmonyLib; using UnityEngine; using static BetterStats.BetterStats; @@ -24,30 +23,22 @@ public class ItemCalculationRuntimeSetting { private ItemCalculationMode _mode = ItemCalculationMode.Normal; private bool _enabled; + public readonly int productId; - public readonly bool productivitySupported; - public readonly bool speedSupported; + private ConfigEntry _configEntry; private static readonly Dictionary> ConfigEntries = new(); private static readonly Dictionary Pool = new(); private static ConfigFile configFile; - - + private readonly ItemProto _itemProto; private ItemCalculationRuntimeSetting(int productId) { this.productId = productId; - var itemProto = LDB.items.Select(productId); - if (itemProto != null) + var proto = LDB.items.Select(productId); + if (proto != null) { - speedSupported = itemProto.recipes is { Count: > 0 }; - productivitySupported = speedSupported && itemProto.recipes.Any(r => r.productive); - _enabled = speedSupported; + _itemProto = proto; } - - if (productivitySupported) - Log.LogDebug($"productivity supported for {itemProto?.name}"); - else - Log.LogDebug($"NO productivity mode supported for {itemProto?.name}"); } public ItemCalculationMode Mode @@ -63,7 +54,7 @@ public ItemCalculationMode Mode public bool Enabled { - get => _enabled && speedSupported; + get => _enabled; set { _enabled = value; @@ -72,6 +63,13 @@ public bool Enabled } } + public bool SpeedSupported => _itemProto.recipes is { Count: > 0 }; + + public bool ProductivitySupported + { + get { return SpeedSupported && _itemProto.recipes.Any(r => r.productive); } + } + private void Save() { _configEntry.Value = Serialize(); @@ -94,35 +92,33 @@ private string Serialize() return JsonUtility.ToJson(SerializableRuntimeState.From(this)); } - private static void InitConfig(ItemProto itemProto) + public static void InitConfig() { - if (configFile == null) + configFile = new ConfigFile($"{Paths.ConfigPath}/{PluginInfo.PLUGIN_NAME}/CustomProductSettings.cfg", true); + + foreach (var itemProto in LDB.items.dataArray) { - configFile = new ConfigFile($"{Paths.ConfigPath}/{PluginInfo.PLUGIN_NAME}/CustomProductSettings.cfg", true); + var defaultValue = new ItemCalculationRuntimeSetting(itemProto.ID) + { + _enabled = true, + _mode = ItemCalculationMode.Normal + }; + + var configEntry = configFile.Bind("Internal", $"ProliferatorStatsSetting_{itemProto.ID}", + defaultValue.Serialize(), + "For internal use only"); + ConfigEntries[itemProto.ID] = configEntry; + + Pool[itemProto.ID] = Deserialize(ConfigEntries[itemProto.ID].Value); + Pool[itemProto.ID]._configEntry = configEntry; + Log.LogDebug($"Loaded {itemProto.name} runtime settings"); } - - var defaultValue = new ItemCalculationRuntimeSetting(itemProto.ID); - - var configEntry = configFile.Bind("Internal", $"ProliferatorStatsSetting_{itemProto.ID}", - defaultValue.Serialize(), - "For internal use only"); - ConfigEntries[itemProto.ID] = configEntry; - - Pool[itemProto.ID] = Deserialize(ConfigEntries[itemProto.ID].Value); - Pool[itemProto.ID]._configEntry = configEntry; - Log.LogDebug($"Loaded {itemProto.name} runtime settings"); } public static ItemCalculationRuntimeSetting ForItemId(int itemId) { return Pool[itemId]; } - - [HarmonyPostfix, HarmonyPatch(typeof(ItemProto), nameof(ItemProto.Preload))] - public static void UIStatisticsWindow__OnOpen_Postfix(ItemProto __instance) - { - InitConfig(__instance); - } } [Serializable] diff --git a/BetterStats/ProliferatorOperationSetting.cs b/BetterStats/ProliferatorOperationSetting.cs index 91d5870..747974c 100644 --- a/BetterStats/ProliferatorOperationSetting.cs +++ b/BetterStats/ProliferatorOperationSetting.cs @@ -37,13 +37,14 @@ private ProliferatorOperationSetting() public static void Init() { InitSprites(); + ItemCalculationRuntimeSetting.InitConfig(); } private static void InitSprites() { var productivityTexture = Resources.Load("ui/textures/sprites/icons/plus"); - var normalProlifTexture = Resources.Load("ui/textures/sprites/icons/factory-icon"); + var normalProlifTexture = Resources.Load("ui/textures/sprites/icons/voxel-icon"); var speedTexture = Resources.Load("ui/textures/sprites/sci-fi/arrow-mark-60px"); var checkBoxOff = Resources.Load("ui/textures/sprites/icons/checkbox-off"); var checkBoxOn = Resources.Load("ui/textures/sprites/icons/checkbox-on"); @@ -169,12 +170,16 @@ private void SyncButtons() _disableButton.button.image.sprite = checkboxOnSprite; } - foreach (var availableButton in _availableButtons) + if (!runtimeSetting.Enabled) { - if (availableButton == _disableButton) - continue; - availableButton.gameObject - .SetActive(availableButton == _forceProductivityButton ? runtimeSetting.productivitySupported : runtimeSetting.Enabled); + foreach (var availableButton in _availableButtons) + { + if (availableButton == _disableButton) + continue; + availableButton.gameObject + .SetActive(false); + } + return; } switch (runtimeSetting.Mode) @@ -203,13 +208,12 @@ private void SyncButtons() private void ReInitButtonStates() { var runtimeSetting = ItemCalculationRuntimeSetting.ForItemId(_productId); - if (!runtimeSetting.speedSupported) + if (!runtimeSetting.SpeedSupported && !runtimeSetting.ProductivitySupported) { foreach (var button in _availableButtons) { button.gameObject.SetActive(false); } - return; } @@ -218,7 +222,7 @@ private void ReInitButtonStates() _forceProductivityButton.tips.tipTitle = FORCE_PRODUCTIVITY_MODE; _forceProductivityButton.highlighted = false; _forceProductivityButton.button.interactable = true; - _forceProductivityButton.gameObject.SetActive(runtimeSetting.productivitySupported); + _forceProductivityButton.gameObject.SetActive(runtimeSetting.ProductivitySupported); } if (_forceSpeedButton != null) @@ -226,7 +230,7 @@ private void ReInitButtonStates() _forceSpeedButton.tips.tipTitle = FORCE_SPEED_MODE; _forceSpeedButton.highlighted = false; _forceSpeedButton.button.interactable = true; - _forceSpeedButton.gameObject.SetActive(true); + _forceSpeedButton.gameObject.SetActive(runtimeSetting.SpeedSupported); } if (_disableButton != null) @@ -354,6 +358,11 @@ public static ItemCalculationRuntimeSetting ForRecipe(int assemblerRecipeId) // todo figure out better way to manage this _chosenItemIdForRecipeId[assemblerRecipeId] = chosenItemId; + if (chosenItemId == 1120) + { + // hydrogen is kind of boring + chosenItemId = recipeProto.Results[1]; + } Log.LogDebug($"chose {chosenItemId} for recipe {recipeProto.name} (total: {recipeProto.Results.Length})"); return ItemCalculationRuntimeSetting.ForItemId(chosenItemId); } From e4c756eac6faf32d667c6fed37cf03ac66a0ce68 Mon Sep 17 00:00:00 2001 From: Matt Semar Date: Sun, 6 Feb 2022 00:44:18 -0600 Subject: [PATCH 12/16] Hide proliferator UI elements when spray is not unlocked --- BetterStats/BetterStats.cs | 2 +- BetterStats/ProliferatorOperationSetting.cs | 3 +++ BetterStats/ResearchTechHelper.cs | 5 +++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/BetterStats/BetterStats.cs b/BetterStats/BetterStats.cs index 52f056d..b466a7d 100644 --- a/BetterStats/BetterStats.cs +++ b/BetterStats/BetterStats.cs @@ -571,7 +571,7 @@ public static void UIProductEntry__OnUpdate_Postfix(UIProductEntry __instance) if (warnOnHighMaxConsumption && !isTotalTimeWindow) enhancement.maxConsumptionValue.color = new Color(1f, 1f, .25f, .5f); - enhancement.proliferatorOperationSetting.UpdateItemId(__instance.entryData.itemId); + enhancement.proliferatorOperationSetting?.UpdateItemId(__instance.entryData.itemId); } [HarmonyPrefix, HarmonyPatch(typeof(UIStatisticsWindow), "ComputeDisplayEntries")] diff --git a/BetterStats/ProliferatorOperationSetting.cs b/BetterStats/ProliferatorOperationSetting.cs index 747974c..1a9a147 100644 --- a/BetterStats/ProliferatorOperationSetting.cs +++ b/BetterStats/ProliferatorOperationSetting.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using DefaultNamespace; using UnityEngine; using UnityEngine.UI; using static BetterStats.BetterStats; @@ -69,6 +70,8 @@ private static void InitSprites() public static ProliferatorOperationSetting ForProductEntry(UIProductEntry uiProductEntry) { + if (!ResearchTechHelper.IsProliferatorUnlocked()) + return null; var itemId = uiProductEntry.entryData.itemId; ProliferatorOperationSetting result; diff --git a/BetterStats/ResearchTechHelper.cs b/BetterStats/ResearchTechHelper.cs index 30688d4..7863b80 100644 --- a/BetterStats/ResearchTechHelper.cs +++ b/BetterStats/ResearchTechHelper.cs @@ -61,5 +61,10 @@ private static void InitTechProtos() } } } + + public static bool IsProliferatorUnlocked() + { + return GetMaxIncIndex() > 0; + } } } From 33ac3f9bc59c111aa6286c04d45c19f3c563a643 Mon Sep 17 00:00:00 2001 From: Matt Semar Date: Sun, 6 Feb 2022 12:35:21 -0600 Subject: [PATCH 13/16] Fix issue with package script where it would hang after completion --- BetterStats/package.ps1 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/BetterStats/package.ps1 b/BetterStats/package.ps1 index 348b5fe..6fd00b6 100644 --- a/BetterStats/package.ps1 +++ b/BetterStats/package.ps1 @@ -4,8 +4,8 @@ Set-StrictMode -Version Latest write-host "version type $vertype" -Remove-Item .\tmp_release -Force -Recurse -New-Item .\tmp_release -ItemType "directory" -Force +Remove-Item .\tmp_release -Force -Recurse +New-Item .\tmp_release -ItemType "directory" -Force -ErrorAction Stop $manifestContent = Get-Content -path .\manifest.json -Raw $j = $manifestContent | ConvertFrom-Json @@ -45,7 +45,8 @@ $new_version_string = "$([string]::Join(".", $new_version))"; $sourceFileContent -replace $old_vernum, $new_version_string | Set-Content -Path .\BetterStats.csproj -NoNewline -Start-Process dotnet.exe -ArgumentList "build" -Wait +$dotnet_process = Start-Process dotnet.exe -ArgumentList "build" -ErrorAction Stop -NoNewWindow -PassThru +Wait-Process -Id $dotnet_process.Id -ErrorAction Continue Copy-Item -Path bin/Debug/netstandard2.0/BetterStats.dll -Destination tmp_release Copy-Item README.md -Destination tmp_release\README.md From 94abab48ff3fbf5dfec995b5a8234d2354b145c8 Mon Sep 17 00:00:00 2001 From: Matt Semar Date: Sun, 6 Feb 2022 13:17:50 -0600 Subject: [PATCH 14/16] Add config to disable proliferator point calculation --- BetterStats/BetterStats.cs | 8 ++++++-- BetterStats/ItemCalculationMode.cs | 9 +++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/BetterStats/BetterStats.cs b/BetterStats/BetterStats.cs index b466a7d..db41aa4 100644 --- a/BetterStats/BetterStats.cs +++ b/BetterStats/BetterStats.cs @@ -36,6 +36,7 @@ public class EnhancedUIProductEntryElements private static ConfigEntry lackOfProductionRatioTrigger; private static ConfigEntry consumptionToProductionRatioTrigger; private static ConfigEntry displayPerSecond; + public static ConfigEntry disableProliferatorCalc; private static Dictionary counter = new(); private static GameObject txtGO, chxGO, filterGO; private static Texture2D texOff = Resources.Load("ui/textures/sprites/icons/checkbox-off"); @@ -86,6 +87,8 @@ internal void InitConfig() " (e.g. if set to '1.5' then you will be warned if your max consumption is more than 150% of your max production)"); displayPerSecond = Config.Bind("General", "displayPerSecond", false, "Used by UI to persist the last selected value for checkbox"); + disableProliferatorCalc = Config.Bind("General", "Disable Proliferator Calculation", false, + "Tells mod to ignore proliferator points completely. Can cause production rates to exceed theoretical max values"); } internal void OnDestroy() @@ -689,7 +692,8 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) var productionFrequency = baseFrequency; var speed = (float)(0.0001 * (double)assembler.speed); - ItemCalculationRuntimeSetting runtimeSetting = ProliferatorOperationSetting.ForRecipe(assembler.recipeId); + var runtimeSetting = + disableProliferatorCalc.Value ? ItemCalculationRuntimeSetting.None : ProliferatorOperationSetting.ForRecipe(assembler.recipeId); // forceAccMode is 'Production Speedup' mode. It just adds a straight increase to both production and consumption rate if (runtimeSetting.Enabled) @@ -893,7 +897,7 @@ private static (float, float) DetermineLabFrequencies(ref LabComponent lab, floa // when we are in Production Speedup mode `speedOverride` is increased. float baseFrequency = 0f, productionFrequency = 0; - var runtimeSetting = ProliferatorOperationSetting.ForRecipe(lab.recipeId); + var runtimeSetting = disableProliferatorCalc.Value ? ItemCalculationRuntimeSetting.None : ProliferatorOperationSetting.ForRecipe(lab.recipeId); if (runtimeSetting != null && runtimeSetting.Enabled) { diff --git a/BetterStats/ItemCalculationMode.cs b/BetterStats/ItemCalculationMode.cs index 01ca0a5..cfbde1e 100644 --- a/BetterStats/ItemCalculationMode.cs +++ b/BetterStats/ItemCalculationMode.cs @@ -21,6 +21,11 @@ public enum ItemCalculationMode /// public class ItemCalculationRuntimeSetting { + public static readonly ItemCalculationRuntimeSetting None = new(0) + { + _enabled = false, + _mode = ItemCalculationMode.None, + }; private ItemCalculationMode _mode = ItemCalculationMode.Normal; private bool _enabled; @@ -63,7 +68,7 @@ public bool Enabled } } - public bool SpeedSupported => _itemProto.recipes is { Count: > 0 }; + public bool SpeedSupported => _itemProto is { recipes: { Count: > 0 } }; public bool ProductivitySupported { @@ -117,7 +122,7 @@ public static void InitConfig() public static ItemCalculationRuntimeSetting ForItemId(int itemId) { - return Pool[itemId]; + return disableProliferatorCalc.Value ? None : Pool[itemId]; } } From bb8ea4dfbe1c7197f9a2e4970f0e2d4256320234 Mon Sep 17 00:00:00 2001 From: Matt Semar Date: Sun, 6 Feb 2022 17:52:11 -0600 Subject: [PATCH 15/16] Add max consumption for the sprays themselves --- BetterStats/BetterStats.cs | 30 ++++++++++++++++++++++++++++++ BetterStats/ItemCalculationMode.cs | 1 - BetterStats/ResearchTechHelper.cs | 12 ++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/BetterStats/BetterStats.cs b/BetterStats/BetterStats.cs index db41aa4..d02b7dc 100644 --- a/BetterStats/BetterStats.cs +++ b/BetterStats/BetterStats.cs @@ -37,6 +37,7 @@ public class EnhancedUIProductEntryElements private static ConfigEntry consumptionToProductionRatioTrigger; private static ConfigEntry displayPerSecond; public static ConfigEntry disableProliferatorCalc; + public static ConfigEntry disableStackingCalc; private static Dictionary counter = new(); private static GameObject txtGO, chxGO, filterGO; private static Texture2D texOff = Resources.Load("ui/textures/sprites/icons/checkbox-off"); @@ -89,6 +90,8 @@ internal void InitConfig() "Used by UI to persist the last selected value for checkbox"); disableProliferatorCalc = Config.Bind("General", "Disable Proliferator Calculation", false, "Tells mod to ignore proliferator points completely. Can cause production rates to exceed theoretical max values"); + disableStackingCalc = Config.Bind("General", "Disable Stacking Calculation", false, + "Tells mod to ignore unlocked tech for stacking items on belts. By default uses same 'Tech Limit' value as stations use"); } internal void OnDestroy() @@ -889,6 +892,33 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) } } } + + var cargoTraffic = planetFactory.cargoTraffic; + for (int i = 0; i < planetFactory.cargoTraffic.spraycoaterCursor; i++) + { + var sprayCoater = cargoTraffic.spraycoaterPool[i]; + if (sprayCoater.id != i || sprayCoater.incItemId < 1) + continue; + ItemProto itemProto = LDB.items.Select(sprayCoater.incItemId); + var beltComponent = cargoTraffic.beltPool[sprayCoater.cargoBeltId]; + // Belt running at 6 / s transports 360 cargos in 1 minute + // Tooltip for spray lvl 1 shows: "Numbers of sprays = 12", which means that + // each spray covers 12 cargos so 360 / 12 = 30 items are covered per minute + // (HpMax from proto == Numbers of Sprays) + // For now, since we're computing max consumption of the sprays, don't worry about sprays + // that are themselves sprayed since that would lead to lower consumption + var numbersOfSprays = itemProto.HpMax; + + // beltspeed is 1,2,5 so must be multiplied by 6 to get 6,12,30 + var beltRatePerMin = 6 * beltComponent.speed * 60; + int beltMaxStack = ResearchTechHelper.GetMaxPilerStackingUnlocked(); + var frequency = beltMaxStack * beltRatePerMin / (float) numbersOfSprays; + var productId = sprayCoater.incItemId; + EnsureId(ref counter, productId); + + counter[productId].consumption += frequency; + counter[productId].consumers++; + } } private static (float, float) DetermineLabFrequencies(ref LabComponent lab, float maxProductivityIncrease, float maxSpeedIncrease) diff --git a/BetterStats/ItemCalculationMode.cs b/BetterStats/ItemCalculationMode.cs index cfbde1e..05eb427 100644 --- a/BetterStats/ItemCalculationMode.cs +++ b/BetterStats/ItemCalculationMode.cs @@ -116,7 +116,6 @@ public static void InitConfig() Pool[itemProto.ID] = Deserialize(ConfigEntries[itemProto.ID].Value); Pool[itemProto.ID]._configEntry = configEntry; - Log.LogDebug($"Loaded {itemProto.name} runtime settings"); } } diff --git a/BetterStats/ResearchTechHelper.cs b/BetterStats/ResearchTechHelper.cs index 7863b80..7a2a728 100644 --- a/BetterStats/ResearchTechHelper.cs +++ b/BetterStats/ResearchTechHelper.cs @@ -66,5 +66,17 @@ public static bool IsProliferatorUnlocked() { return GetMaxIncIndex() > 0; } + + public static int GetMaxPilerStackingUnlocked() + { + if (BetterStats.BetterStats.disableStackingCalc.Value) + { + return 1; + } + var stationPilerLevel1 = GameMain.history.TechUnlocked(3801) ? 1 + (int)LDB.techs.Select(3801).UnlockValues[0] : 1; + var stationPilerLevel2 = GameMain.history.TechUnlocked(3802) ? stationPilerLevel1 + (int)LDB.techs.Select(3802).UnlockValues[0] : stationPilerLevel1; + var maxStationPilerTech = GameMain.history.TechUnlocked(3803) ? stationPilerLevel2 + (int)LDB.techs.Select(3803).UnlockValues[0] : stationPilerLevel2; + return maxStationPilerTech; + } } } From 9a3dd261c42e14084a49ed06da8d5640f198d9f9 Mon Sep 17 00:00:00 2001 From: Matt Semar Date: Mon, 14 Mar 2022 11:10:50 -0500 Subject: [PATCH 16/16] Fix handling of recipes/items added after startup. Fix detection of non-productive assembler recipe default mode --- BetterStats/BetterStats.cs | 3 ++- BetterStats/ItemCalculationMode.cs | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/BetterStats/BetterStats.cs b/BetterStats/BetterStats.cs index d02b7dc..4f0007c 100644 --- a/BetterStats/BetterStats.cs +++ b/BetterStats/BetterStats.cs @@ -691,6 +691,7 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) var assembler = factorySystem.assemblerPool[i]; if (assembler.id != i || assembler.recipeId == 0) continue; + var isNonProductiveRecipe = LDB.recipes.Select(assembler.recipeId).NonProductive; var baseFrequency = 60f / (float)(assembler.timeSpend / 600000.0); var productionFrequency = baseFrequency; var speed = (float)(0.0001 * (double)assembler.speed); @@ -704,7 +705,7 @@ public static void AddPlanetFactoryData(PlanetFactory planetFactory) if (runtimeSetting.Mode == ItemCalculationMode.Normal) { // let assembler decide - if (assembler.forceAccMode) + if (assembler.forceAccMode || isNonProductiveRecipe) { speed += speed * maxSpeedIncrease; } diff --git a/BetterStats/ItemCalculationMode.cs b/BetterStats/ItemCalculationMode.cs index 05eb427..464e2bb 100644 --- a/BetterStats/ItemCalculationMode.cs +++ b/BetterStats/ItemCalculationMode.cs @@ -121,7 +121,25 @@ public static void InitConfig() public static ItemCalculationRuntimeSetting ForItemId(int itemId) { - return disableProliferatorCalc.Value ? None : Pool[itemId]; + if (disableProliferatorCalc.Value) + return None; + if (Pool.ContainsKey(itemId)) + return Pool[itemId]; + + var defaultValue = new ItemCalculationRuntimeSetting(itemId) + { + _enabled = true, + _mode = ItemCalculationMode.Normal + }; + + var configEntry = configFile.Bind("Internal", $"ProliferatorStatsSetting_{itemId}", + defaultValue.Serialize(), + "For internal use only"); + ConfigEntries[itemId] = configEntry; + + Pool[itemId] = Deserialize(ConfigEntries[itemId].Value); + Pool[itemId]._configEntry = configEntry; + return Pool[itemId]; } }