Ejemplo n.º 1
0
        protected override void FillTab()
        {
            Text.Font = GameFont.Small;
            const float Padding = 10f, Spacing = 6f, SettingsRowHeight = 29f;
            var         canvasRect = new Rect(0f, 18f, WinSize.x, WinSize.y).ContractedBy(Padding);

            var settingsRect = new Rect(canvasRect.x, canvasRect.y, canvasRect.width, Padding * 2f + SettingsRowHeight * 3f + Spacing * 2f);

            Widgets.DrawMenuSection(settingsRect);
            var settingsContent = settingsRect.ContractedBy(Padding);

            Text.Anchor = TextAnchor.MiddleLeft;
            var rowRect            = new Rect(settingsContent.x, settingsContent.y, settingsContent.width, SettingsRowHeight);
            var sparkpowderVariant = (currentVariant & RecipeVariantType.Sparkpowder) != 0;

            Widgets.Label(rowRect, "BillsTab_MainMaterial_label".Translate());
            if (Widgets.ButtonText(rowRect.RightHalf(), sparkpowderVariant ? "BillsTab_MaterialButton_sparkpowder_mode".Translate() : "BillsTab_MaterialButton_silver_mode".Translate()))
            {
                currentVariant ^= RecipeVariantType.Sparkpowder;
            }

            rowRect.y += SettingsRowHeight + Spacing;
            var steelVariant = (currentVariant & RecipeVariantType.Steel) != 0;

            Widgets.Label(rowRect, "BillsTab_SecondaryMaterial_label".Translate());
            if (Widgets.ButtonText(rowRect.RightHalf(), steelVariant ? "BillsTab_MaterialButton_steel_mode".Translate() : "BillsTab_MaterialButton_component_mode".Translate()))
            {
                currentVariant ^= RecipeVariantType.Steel;
            }

            rowRect.y += SettingsRowHeight + Spacing;
            Widgets.Label(rowRect, "BillsTab_WorkAmount_label".Translate());
            var workPercent = 100f * (sparkpowderVariant ? RemoteTechController.SilverReplacementWorkMultiplier : 1f) *
                              (steelVariant ? RemoteTechController.ComponentReplacementWorkMultiplier : 1f);

            Widgets.Label(rowRect.RightHalf(), $"{workPercent:F0}%");
            Text.Anchor = TextAnchor.UpperLeft;

            const float InfoBtnSize = 24f;
            var         infoRect    = new Rect(rowRect.xMax - InfoBtnSize, rowRect.y + (rowRect.height - InfoBtnSize) / 2f, InfoBtnSize, InfoBtnSize);

            TooltipHandler.TipRegion(infoRect, "BillsTab_Materials_info".Translate());
            GUI.DrawTexture(infoRect, Resources.Textures.InfoButtonIcon);

            var recipesRect = new Rect(canvasRect.x, canvasRect.y + settingsRect.height + Spacing, canvasRect.width, canvasRect.height - (settingsRect.height + Spacing));

            List <FloatMenuOption> RecipeOptionsMaker()
            {
                var list = new List <FloatMenuOption>();

                for (int i = 0; i < SelTable.def.AllRecipes.Count; i++)
                {
                    var recipe  = SelTable.def.AllRecipes[i];
                    var variant = recipe.GetModExtension <MakeRecipeVariants>();
                    if (variant != null && variant.Variant != currentVariant)
                    {
                        continue;
                    }

                    var    locked      = recipe.researchPrerequisite != null && !recipe.AvailableNow && !DebugSettings.godMode;
                    string researchTip = "";
                    if (locked)
                    {
                        researchTip = "BillsTab_ResearchRequired".Translate(recipe.researchPrerequisite.label);
                    }
                    var option = new FloatMenuOptionWithTooltip(recipe.LabelCap, delegate {
                        var map = Find.CurrentMap;
                        if (map == null || !map.mapPawns.FreeColonists.Any(recipe.PawnSatisfiesSkillRequirements))
                        {
                            Bill.CreateNoPawnsWithSkillDialog(recipe);
                        }
                        var bill = recipe.MakeNewBill();
                        SelTable.billStack.AddBill(bill);
                    }, researchTip, MenuOptionPriority.Default, null, null, 29f, rect => Widgets.InfoCardButton(rect.x + 5f, rect.y + (rect.height - 24f) / 2f, recipe));
                    option.Disabled = locked;
                    list.Add(option);
                }
                if (list.Count == 0)
                {
                    list.Add(new FloatMenuOption("(no recipes)", null));
                }
                return(list);
            }

            mouseoverBill = SelTable.billStack.DoListing(recipesRect, RecipeOptionsMaker, ref scrollPosition, ref viewHeight);
        }
        /// <summary>
        /// Generates a copy of a given recipe with the provided ingredient replaced with another, at the given ratio.
        ///  Will return null if recipe requires none of the original ingredient.
        /// </summary>
        private RecipeDef TryMakeRecipeVariant(RecipeDef recipeOriginal, RecipeVariantType variant, ThingDef originalIngredient, ThingDef replacementIngredient, float replacementRatio, float workAmountMultiplier)
        {
            // check original recipe for the replaced ingredient, copy other ingredients
            var resourceCountRequired = 0f;
            var newIngredientList     = new List <IngredientCount>(recipeOriginal.ingredients);

            foreach (var ingredientCount in newIngredientList)
            {
                if (ingredientCount.filter.Allows(originalIngredient))
                {
                    resourceCountRequired = ingredientCount.GetBaseCount();
                    newIngredientList.Remove(ingredientCount);
                    break;
                }
            }
            if (resourceCountRequired < float.Epsilon)
            {
                return(null);
            }

            var recipeCopy = CloneObject(recipeOriginal);

            recipeCopy.defName   = $"{recipeOriginal.defName}_{replacementIngredient.defName}";
            recipeCopy.shortHash = 0;
            InjectedDefHasher.GiveShortHashToDef(recipeCopy, typeof(RecipeDef));
            // clone our extension to avoid polluting the original def
            recipeCopy.modExtensions = recipeCopy.modExtensions?.Select(e => e is ICloneable i ? (DefModExtension)i.Clone() : e).ToList();
            if (!recipeOriginal.HasModExtension <MakeRecipeVariants>())
            {
                // mark original as a variant, as well
                recipeOriginal.modExtensions = recipeOriginal.modExtensions ?? new List <DefModExtension>();
                recipeOriginal.modExtensions.Add(new MakeRecipeVariants());
            }

            // mark the copy as variant
            var variantExtension = recipeCopy.GetModExtension <MakeRecipeVariants>();

            if (variantExtension == null)
            {
                variantExtension         = new MakeRecipeVariants();
                recipeCopy.modExtensions = recipeCopy.modExtensions ?? new List <DefModExtension>();
                recipeCopy.modExtensions.Add(variantExtension);
            }
            variantExtension.Variant |= variant;

            // copy non-replaced ingredients over to the new filter
            var newFixedFilter = new ThingFilter();

            foreach (var allowedThingDef in recipeOriginal.fixedIngredientFilter.AllowedThingDefs)
            {
                if (allowedThingDef != originalIngredient)
                {
                    newFixedFilter.SetAllow(allowedThingDef, true);
                }
            }
            newFixedFilter.SetAllow(replacementIngredient, true);
            recipeCopy.fixedIngredientFilter   = newFixedFilter;
            recipeCopy.defaultIngredientFilter = null;

            // add the replacement ingredient
            var replacementIngredientFilter = new ThingFilter();

            replacementIngredientFilter.SetAllow(replacementIngredient, true);
            var replacementCount = new IngredientCount {
                filter = replacementIngredientFilter
            };

            replacementCount.SetBaseCount(Mathf.Round(resourceCountRequired * replacementRatio));
            newIngredientList.Add(replacementCount);
            recipeCopy.ingredients = newIngredientList;

            // multiply work amount
            recipeCopy.workAmount = recipeOriginal.workAmount * workAmountMultiplier;

            recipeCopy.ResolveReferences();
            return(recipeCopy);
        }