diff --git a/Yafc.Model/Data/DataClasses.cs b/Yafc.Model/Data/DataClasses.cs index fe4c7782..e7d8c21f 100644 --- a/Yafc.Model/Data/DataClasses.cs +++ b/Yafc.Model/Data/DataClasses.cs @@ -155,6 +155,7 @@ public class Recipe : RecipeOrTechnology { public AllowedEffects allowedEffects { get; internal set; } public string[]? allowedModuleCategories { get; internal set; } public Technology[] technologyUnlock { get; internal set; } = []; + public Dictionary technologyProductivity { get; internal set; } = []; public bool HasIngredientVariants() { foreach (var ingredient in ingredients) { if (ingredient.variants != null) { @@ -522,7 +523,8 @@ public class EntityContainer : Entity { public class Technology : RecipeOrTechnology { // Technology is very similar to recipe public float count { get; internal set; } // TODO support formula count public Technology[] prerequisites { get; internal set; } = []; - public Recipe[] unlockRecipes { get; internal set; } = []; + public List unlockRecipes { get; internal set; } = []; + public Dictionary changeRecipeProductivity { get; internal set; } = []; internal override FactorioObjectSortOrder sortingOrder => FactorioObjectSortOrder.Technologies; public override string type => "Technology"; diff --git a/Yafc.Model/Model/Project.cs b/Yafc.Model/Model/Project.cs index 03c1ebd4..c6dd8064 100644 --- a/Yafc.Model/Model/Project.cs +++ b/Yafc.Model/Model/Project.cs @@ -221,6 +221,7 @@ public class ProjectSettings(Project project) : ModelObject(project) { public float miningProductivity { get; set; } public float researchSpeedBonus { get; set; } public float researchProductivity { get; set; } + public Dictionary productivityTechnologyLevels { get; } = []; public int reactorSizeX { get; set; } = 2; public int reactorSizeY { get; set; } = 2; public float PollutionCostModifier { get; set; } = 0; diff --git a/Yafc.Model/Model/RecipeParameters.cs b/Yafc.Model/Model/RecipeParameters.cs index 1e936430..0c305661 100644 --- a/Yafc.Model/Model/RecipeParameters.cs +++ b/Yafc.Model/Model/RecipeParameters.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; namespace Yafc.Model; @@ -125,6 +126,16 @@ public static RecipeParameters CalculateParameters(RecipeRow row) { else if (recipe is Technology) { productivity += Project.current.settings.researchProductivity; } + else if (recipe is Recipe actualRecipe) { + Dictionary levels = Project.current.settings.productivityTechnologyLevels; + foreach ((Technology productivityTechnology, float changePerLevel) in actualRecipe.technologyProductivity) { + if (!levels.TryGetValue(productivityTechnology, out int productivityTechLevel)) { + continue; + } + + productivity += changePerLevel * productivityTechLevel; + } + } if (entity is EntityReactor reactor && reactor.reactorNeighborBonus > 0f) { productivity += reactor.reactorNeighborBonus * Project.current.settings.GetReactorBonusMultiplier(); diff --git a/Yafc.Parser/Data/FactorioDataDeserializer_RecipeAndTechnology.cs b/Yafc.Parser/Data/FactorioDataDeserializer_RecipeAndTechnology.cs index 36014170..82c35cfa 100644 --- a/Yafc.Parser/Data/FactorioDataDeserializer_RecipeAndTechnology.cs +++ b/Yafc.Parser/Data/FactorioDataDeserializer_RecipeAndTechnology.cs @@ -118,9 +118,32 @@ private void LoadTechnologyData(Technology technology, LuaTable table, ErrorColl } if (table.Get("effects", out LuaTable? modifiers)) { - technology.unlockRecipes = modifiers.ArrayElements() - .Select(x => x.Get("type", out string? type) && type == "unlock-recipe" && GetRef(x, "recipe", out var recipe) ? recipe : null).WhereNotNull() - .ToArray(); + foreach (LuaTable modifier in modifiers.ArrayElements()) { + switch (modifier.Get("type", "")) { + case "unlock-recipe": { + if (!GetRef(modifier, "recipe", out var recipe)) { + continue; + } + + technology.unlockRecipes.Add(recipe); + + break; + } + + case "change-recipe-productivity": { + if (!GetRef(modifier, "recipe", out var recipe)) { + continue; + } + + float change = modifier.Get("change", 0f); + + technology.changeRecipeProductivity.Add(recipe, change); + recipe.technologyProductivity.Add(technology, change); + + break; + } + } + } } } diff --git a/Yafc.UI/ImGui/ImGuiLayout.cs b/Yafc.UI/ImGui/ImGuiLayout.cs index 1ed4c40c..238215ee 100644 --- a/Yafc.UI/ImGui/ImGuiLayout.cs +++ b/Yafc.UI/ImGui/ImGuiLayout.cs @@ -289,7 +289,7 @@ public void StartNextAllocatePass(bool alsoDraw) { public void Dispose() { gui.enableDrawing = initialDrawState; - gui.state.top = maximumBottom; + gui.state.top = Math.Max(gui.state.top, maximumBottom); } } diff --git a/Yafc/Widgets/ObjectTooltip.cs b/Yafc/Widgets/ObjectTooltip.cs index 623d33d2..744d65b4 100644 --- a/Yafc/Widgets/ObjectTooltip.cs +++ b/Yafc/Widgets/ObjectTooltip.cs @@ -531,7 +531,7 @@ private void BuildTechnology(Technology technology, ImGui gui) { } } - if (technology.unlockRecipes.Length > 0) { + if (technology.unlockRecipes.Count > 0) { BuildSubHeader(gui, "Unlocks recipes"); using (gui.EnterGroup(contentPadding)) { BuildIconRow(gui, technology.unlockRecipes, 2); diff --git a/Yafc/Windows/PreferencesScreen.cs b/Yafc/Windows/PreferencesScreen.cs index 8207dbfc..593b4163 100644 --- a/Yafc/Windows/PreferencesScreen.cs +++ b/Yafc/Windows/PreferencesScreen.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using Yafc.Model; using Yafc.UI; @@ -72,6 +74,20 @@ private static void DrawProgression(ImGui gui) { Project.current.settings.RecordUndo().researchProductivity = amount.Value; } } + + IEnumerable productivityTech = Database.technologies.all + .Where(x => x.changeRecipeProductivity.Count != 0) + .OrderBy(x => x.locName); + foreach (var tech in productivityTech) { + using (gui.EnterRow()) { + gui.BuildFactorioObjectButton(tech, ButtonDisplayStyle.Default); + gui.BuildText($"{tech.locName} Level: ", topOffset: 0.5f); + int currentLevel = Project.current.settings.productivityTechnologyLevels.GetValueOrDefault(tech, 0); + if (gui.BuildIntegerInput(currentLevel, out int newLevel) && newLevel >= 0) { + Project.current.settings.RecordUndo().productivityTechnologyLevels[tech] = newLevel; + } + } + } } private static void DrawGeneral(ImGui gui) {