public static IEnumerable <StatDrawEntry> Postfix(IEnumerable <StatDrawEntry> values, Thing thing) { foreach (StatDrawEntry entry in values) { yield return(entry); } if (thing.def.IsWeapon) { string tech = TechTracker.FindTech(thing.def)?.Tech.LabelCap ?? "None".Translate(); yield return(new StatDrawEntry(StatCategoryDefOf.Weapon, "WeaponAssociatedTech".Translate(), tech, "WeaponAssociatedTechDesc".Translate(), 10000, null, null, false)); bool known = unlocked.weapons.Contains(thing.def); yield return(new StatDrawEntry(StatCategoryDefOf.Weapon, "WeaponKnown".Translate(), known.ToStringYesNo(), "WeaponKnownDesc".Translate(), 9999, null, null, false)); bool free = SimpleWeapons.Contains(thing.def) || UniversalWeapons.Contains(thing.def); yield return(new StatDrawEntry(StatCategoryDefOf.Weapon, "WeaponRequiresTraining".Translate(), (!free).ToStringYesNo(), "WeaponRequiresTrainingDesc".Translate(), 9998, null, null, false)); } }
public override void DefsLoaded() { //1. Preparing settings UpdateSettings(); //2. Adding Tech Tab to Pawns //ThingDef injection stolen from the work of notfood for Psychology var zombieThinkTree = DefDatabase <ThinkTreeDef> .GetNamedSilentFail("Zombie"); IEnumerable <ThingDef> things = (from def in DefDatabase <ThingDef> .AllDefs where def.race?.intelligence == Intelligence.Humanlike && (zombieThinkTree == null || def.race.thinkTreeMain != zombieThinkTree) select def); List <string> registered = new List <string>(); foreach (ThingDef t in things) { if (t.inspectorTabsResolved == null) { t.inspectorTabsResolved = new List <InspectTabBase>(1); } t.inspectorTabsResolved.Add(InspectTabManager.GetSharedInstance(typeof(ITab_PawnKnowledge))); if (t.comps == null) { t.comps = new List <CompProperties>(1); } t.comps.Add(new CompProperties_Knowledge()); registered.Add(t.defName); } InspectPaneUtility.Reset(); //3. Preparing knowledge support infrastructure //a. Things everyone knows UniversalWeapons.AddRange(DefDatabase <ThingDef> .AllDefs.Where(x => x.IsWeapon)); UniversalCrops.AddRange(DefDatabase <ThingDef> .AllDefs.Where(x => x.plant != null && x.plant.Sowable)); //b. Minus things unlocked on research ThingFilter lateFilter = new ThingFilter(); foreach (ResearchProjectDef tech in DefDatabase <ResearchProjectDef> .AllDefs) { tech.InferSkillBias(); tech.CreateStuff(lateFilter, unlocked); foreach (ThingDef weapon in tech.UnlockedWeapons()) { UniversalWeapons.Remove(weapon); } foreach (ThingDef plant in tech.UnlockedPlants()) { UniversalCrops.Remove(plant); } } ; //c. Also removing atipical weapons List <string> ForbiddenWeaponTags = TechDefOf.WeaponsNotBasic.weaponTags; UniversalWeapons.RemoveAll(x => SplitSimpleWeapons(x, ForbiddenWeaponTags)); List <ThingDef> garbage = new List <ThingDef>(); garbage.Add(TechDefOf.WeaponsNotBasic); //d. Classifying pawn backstories PawnBackgroundUtility.BuildCache(); //e. Telling humans what's going on ThingCategoryDef knowledgeCat = TechDefOf.Knowledge; IEnumerable <ThingDef> codifiedTech = DefDatabase <ThingDef> .AllDefs.Where(x => x.IsWithinCategory(knowledgeCat)); if (Prefs.LogVerbose || FullStartupReport) { Log.Message($"[HumanResources] Codified technologies: {codifiedTech.Select(x => x.label).ToStringSafeEnumerable()}"); Log.Message($"[HumanResources] Basic crops: {UniversalCrops.ToStringSafeEnumerable()}"); Log.Message($"[HumanResources] Basic weapons: {UniversalWeapons.ToStringSafeEnumerable()}"); Log.Message($"[HumanResources] Basic weapons that require training: {SimpleWeapons.ToStringSafeEnumerable()}"); Log.Warning($"[HumanResources] Basic weapons tags: {SimpleWeapons.Where(x => !x.weaponTags.NullOrEmpty()).SelectMany(x => x.weaponTags).Distinct().ToStringSafeEnumerable()}"); if (FullStartupReport) { Log.Warning("[HumanResources] Backstories classified by TechLevel:"); for (int i = 0; i < 8; i++) { TechLevel level = (TechLevel)i; IEnumerable <string> found = PawnBackgroundUtility.TechLevelByBackstory.Where(e => e.Value == level).Select(e => e.Key); if (!found.EnumerableNullOrEmpty()) { Log.Message($"- {level.ToString().CapitalizeFirst()} ({found.EnumerableCount()}): {found.ToStringSafeEnumerable()}"); } } Log.Warning("[HumanResources] Techs classified by associated skill:"); var skills = DefDatabase <SkillDef> .AllDefsListForReading.GetEnumerator(); while (skills.MoveNext()) { SkillDef skill = skills.Current; IEnumerable <string> found = TechTracker.FindTechs(skill).Select(x => x.Tech.label); Log.Message($"- {skill.LabelCap} ({found.EnumerableCount()}): {found.ToStringSafeEnumerable()}"); } } } else { Log.Message($"[HumanResources] This is what we know: {codifiedTech.EnumerableCount()} technologies processed, {UniversalCrops.Count()} basic crops, {UniversalWeapons.Count()} basic weapons + {SimpleWeapons.Count()} that require training."); } //4. Filling gaps on the database //a. TechBook dirty trick, but only now this is possible! TechDefOf.TechBook.stuffCategories = TechDefOf.UnfinishedTechBook.stuffCategories = TechDefOf.LowTechCategories.stuffCategories; TechDefOf.TechDrive.stuffCategories = TechDefOf.HiTechCategories.stuffCategories; garbage.Add(TechDefOf.LowTechCategories); garbage.Add(TechDefOf.HiTechCategories); //b. Filling main tech category with subcategories foreach (ThingDef t in lateFilter.AllowedThingDefs.Where(t => !t.thingCategories.NullOrEmpty())) { foreach (ThingCategoryDef c in t.thingCategories) { c.childThingDefs.Add(t); if (!knowledgeCat.childCategories.NullOrEmpty() && !knowledgeCat.childCategories.Contains(c)) { knowledgeCat.childCategories.Add(c); } } } //c. Populating knowledge recipes and book shelves foreach (RecipeDef r in DefDatabase <RecipeDef> .AllDefs.Where(x => x.ingredients.Count == 1 && x.fixedIngredientFilter.AnyAllowedDef == null)) { r.fixedIngredientFilter.ResolveReferences(); r.defaultIngredientFilter.ResolveReferences(); } foreach (ThingDef t in DefDatabase <ThingDef> .AllDefs.Where(x => x.thingClass == typeof(Building_BookStore))) { t.building.fixedStorageSettings.filter.ResolveReferences(); t.building.defaultStorageSettings.filter.ResolveReferences(); } //d. Removing temporary defs from database. foreach (ThingDef def in garbage) { AccessTools.Method(typeof(DefDatabase <ThingDef>), "Remove").Invoke(this, new object[] { def }); } }