SOLVED: C# RecipeDef created at Run-Time

Started by AnimateDream, February 12, 2023, 02:22:13 PM

Previous topic - Next topic

AnimateDream

EDIT:
Figured out my original issue with recipe ingredients. Embarrassingly simple to debug when I gave it a fresh set of eyes days later. The ingredients issue was just in how I created the filters. It seems a lot of things in RimWorld can't be set in the objects construction and have to be set using methods after the object is created.

Corrected makeFilter function:
Func<string, ThingFilter> makeFilter = (string s) =>
{
    var category = DefDatabase<ThingCategoryDef>.GetNamed(s);
    if (category == null)
    {
        Log.Error($"Could not find ThingCategoryDef named {s}");
        return null;
    }
    var output = new ThingFilter();
    output.SetAllow(category, true);
    output.ResolveReferences();
    output.RecalculateDisplayRootCategory();
    //output.customSummary = category.ToString();
    //output.customSummary = $"{category.ToString()}: {output.Summary}";
    return output;
};

Now I can't understand why my recipes still don't work when added to my new work bench, but that's too different from the original topic. A new thread may be justified. Leaving the original post up for others who encounter similar problems.

ORIGINAL POST BELOW:


The nature of the mod I'm working on requires a lot of Defs to be created after the game is launched, not from XMLs.

https://github.com/StephenLujan/Rimworld-Archipelago-Mod


This is working fine for ResearchProjectDefs, but specifically ingredients for RecipeDefs have me a bit stumped.
The code looks to me like it should work, but in game when you go to add a bill, the ingredients just say
QuoteRequires:
- 2x: Ingredients
I'm hoping someone might be experienced enough to see the problem or suggest some troubleshooting steps with the below code.
        private void LoadCraftDefs()
        {
            //get new archipelago crafting table and other constant recipe properties
            var recipeUsers = new List<ThingDef>() { DefDatabase<ThingDef>.GetNamed("AD_ArchipelagoBench") };
            var workSkill = DefDatabase<SkillDef>.GetNamed("Crafting");
            var effectWorking = DefDatabase<EffecterDef>.GetNamed("Cook");
            var soundWorking = DefDatabase<SoundDef>.GetNamed("Recipe_Machining");
            var workSpeedStat = DefDatabase<StatDef>.GetNamed("GeneralLaborSpeed");

            /*
            * Log.Message(string.Join(", " , DefDatabase<ThingCategoryDef>.AllDefsListForReading.Select(x => x.defName).ToArray()));
            * Root, Foods, FoodMeals, FoodRaw, MeatRaw, PlantFoodRaw, AnimalProductRaw, EggsUnfertilized, EggsFertilized, Manufactured,
            * Textiles, Leathers, Wools, Medicine, Drugs, MortarShells, ResourcesRaw, PlantMatter, StoneBlocks, Items, Unfinished, Artifacts,
            * InertRelics, Neurotrainers, NeurotrainersPsycast, NeurotrainersSkill, Techprints, BodyParts, BodyPartsNatural, BodyPartsSimple,
            * BodyPartsProsthetic, BodyPartsBionic, BodyPartsUltra, BodyPartsArchotech, BodyPartsMechtech, ItemsMisc, Weapons, WeaponsMelee,
            * WeaponsMeleeBladelink, WeaponsRanged, Grenades, Apparel, Headgear, ApparelArmor, ArmorHeadgear, ApparelUtility, ApparelNoble,
            * HeadgearNoble, ApparelMisc, Buildings, BuildingsArt, BuildingsProduction, BuildingsFurniture, BuildingsPower, BuildingsSecurity,
            * BuildingsMisc, BuildingsJoy, BuildingsTemperature, BuildingsSpecial, Chunks, StoneChunks, Animals, Plants, Stumps, Corpses,
            * CorpsesHumanlike, CorpsesAnimal, CorpsesInsect, CorpsesMechanoid
            */

            Func<string, ThingFilter> makeFilter = (string s) => new ThingFilter()
            {
                DisplayRootCategory = DefDatabase<ThingCategoryDef>.GetNamed(s).treeNode
            };

            var leathersFilter = makeFilter("Leathers");
            var textilesFilter = makeFilter("Textiles");
            var woolsFilter = makeFilter("Textiles");
            var stoneBlocksFilter = makeFilter("StoneBlocks");
            var foodRawFilter = makeFilter("FoodRaw");
            var filters = new List<ThingFilter>() { leathersFilter, textilesFilter, woolsFilter, stoneBlocksFilter, foodRawFilter };

            Func<ThingFilter, float, IngredientCount> makeIngredientCount = (ThingFilter filter, float count) =>
            {
                var output = new IngredientCount()
                {
                    filter = filter,
                };
                output.SetBaseCount(count);
                return output;
            };

            foreach (var kvp in CraftLocations)
            {

                // TODO get ingredients from archipelago
                var filter = Verse.Rand.Element(leathersFilter, textilesFilter, woolsFilter, stoneBlocksFilter, foodRawFilter);
                var def = new RecipeDef()
                {
                    defName = $"AP_{kvp.Key}",
                    label = kvp.Value.ExtendedLabel,
                    description = kvp.Value.ExtendedLabel + $" (AP_{kvp.Key})",
                    recipeUsers = recipeUsers,
                    workerClass = typeof(ArchipelagoRecipeWorker),
                    workSkill = workSkill,
                    workAmount = 1000, //TODO get workAmount from archipelago
                    workSpeedStat = workSpeedStat,
                    allowMixingIngredients = true,
                    effectWorking = effectWorking,
                    soundWorking = soundWorking,
                    ingredients = new List<IngredientCount>()
                    {
                        makeIngredientCount(filter, 2)
                    },
                    fixedIngredientFilter = filter,
                    defaultIngredientFilter = filter,
                    targetCountAdjustment = 1
                };
                AddedRecipeDefs.Add(kvp.Key, def);
                Main.Instance.DefNameToArchipelagoId[def.defName] = kvp.Key;
            }
            DefDatabase<RecipeDef>.Add(AddedRecipeDefs.Values);
        }