private static Pawn TryGenerateNewPawnInternal(ref PawnGenerationRequest request, out string error, bool ignoreScenarioRequirements, bool ignoreValidator)
        {
            error = null;
            Pawn pawn = (Pawn)ThingMaker.MakeThing(request.KindDef.race, null);

            PawnGenerator.pawnsBeingGenerated.Add(new PawnGenerator.PawnGenerationStatus(pawn, null));
            Pawn result;

            try
            {
                pawn.kindDef = request.KindDef;
                pawn.SetFactionDirect(request.Faction);
                PawnComponentsUtility.CreateInitialComponents(pawn);
                if (request.FixedGender.HasValue)
                {
                    pawn.gender = request.FixedGender.Value;
                }
                else if (pawn.RaceProps.hasGenders)
                {
                    if (Rand.Value < 0.5f)
                    {
                        pawn.gender = Gender.Male;
                    }
                    else
                    {
                        pawn.gender = Gender.Female;
                    }
                }
                else
                {
                    pawn.gender = Gender.None;
                }
                PawnGenerator.GenerateRandomAge(pawn, request);
                pawn.needs.SetInitialLevels();
                if (!request.Newborn && request.CanGeneratePawnRelations)
                {
                    PawnGenerator.GeneratePawnRelations(pawn, ref request);
                }
                if (pawn.RaceProps.Humanlike)
                {
                    FactionDef def;
                    Faction    faction;
                    if (request.Faction != null)
                    {
                        def = request.Faction.def;
                    }
                    else if (Find.FactionManager.TryGetRandomNonColonyHumanlikeFaction(out faction, false, true, TechLevel.Undefined))
                    {
                        def = faction.def;
                    }
                    else
                    {
                        def = Faction.OfAncients.def;
                    }
                    pawn.story.melanin   = ((!request.FixedMelanin.HasValue) ? PawnSkinColors.RandomMelanin(request.Faction) : request.FixedMelanin.Value);
                    pawn.story.crownType = ((Rand.Value >= 0.5f) ? CrownType.Narrow : CrownType.Average);
                    pawn.story.hairColor = PawnHairColors.RandomHairColor(pawn.story.SkinColor, pawn.ageTracker.AgeBiologicalYears);
                    PawnBioAndNameGenerator.GiveAppropriateBioAndNameTo(pawn, request.FixedLastName, def);
                    pawn.story.hairDef = PawnHairChooser.RandomHairDefFor(pawn, def);
                    PawnGenerator.GenerateTraits(pawn, request);
                    PawnGenerator.GenerateBodyType(pawn);
                    PawnGenerator.GenerateSkills(pawn);
                }
                if (pawn.RaceProps.Animal && request.Faction != null && request.Faction.IsPlayer)
                {
                    pawn.training.SetWantedRecursive(TrainableDefOf.Tameness, true);
                    pawn.training.Train(TrainableDefOf.Tameness, null, true);
                }
                PawnGenerator.GenerateInitialHediffs(pawn, request);
                if (pawn.workSettings != null && request.Faction != null && request.Faction.IsPlayer)
                {
                    pawn.workSettings.EnableAndInitialize();
                }
                if (request.Faction != null && pawn.RaceProps.Animal)
                {
                    pawn.GenerateNecessaryName();
                }
                if (Find.Scenario != null)
                {
                    Find.Scenario.Notify_NewPawnGenerating(pawn, request.Context);
                }
                if (!request.AllowDead && (pawn.Dead || pawn.Destroyed))
                {
                    PawnGenerator.DiscardGeneratedPawn(pawn);
                    error  = "Generated dead pawn.";
                    result = null;
                }
                else if (!request.AllowDowned && pawn.Downed)
                {
                    PawnGenerator.DiscardGeneratedPawn(pawn);
                    error  = "Generated downed pawn.";
                    result = null;
                }
                else if (request.MustBeCapableOfViolence && ((pawn.story != null && pawn.story.WorkTagIsDisabled(WorkTags.Violent)) || (pawn.RaceProps.ToolUser && !pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation))))
                {
                    PawnGenerator.DiscardGeneratedPawn(pawn);
                    error  = "Generated pawn incapable of violence.";
                    result = null;
                }
                else if (!ignoreScenarioRequirements && request.Context == PawnGenerationContext.PlayerStarter && Find.Scenario != null && !Find.Scenario.AllowPlayerStartingPawn(pawn, false, request))
                {
                    PawnGenerator.DiscardGeneratedPawn(pawn);
                    error  = "Generated pawn doesn't meet scenario requirements.";
                    result = null;
                }
                else if (!ignoreValidator && request.ValidatorPreGear != null && !request.ValidatorPreGear(pawn))
                {
                    PawnGenerator.DiscardGeneratedPawn(pawn);
                    error  = "Generated pawn didn't pass validator check (pre-gear).";
                    result = null;
                }
                else
                {
                    if (!request.Newborn)
                    {
                        PawnGenerator.GenerateGearFor(pawn, request);
                    }
                    if (!ignoreValidator && request.ValidatorPostGear != null && !request.ValidatorPostGear(pawn))
                    {
                        PawnGenerator.DiscardGeneratedPawn(pawn);
                        error  = "Generated pawn didn't pass validator check (post-gear).";
                        result = null;
                    }
                    else
                    {
                        for (int i = 0; i < PawnGenerator.pawnsBeingGenerated.Count - 1; i++)
                        {
                            if (PawnGenerator.pawnsBeingGenerated[i].PawnsGeneratedInTheMeantime == null)
                            {
                                PawnGenerator.pawnsBeingGenerated[i] = new PawnGenerator.PawnGenerationStatus(PawnGenerator.pawnsBeingGenerated[i].Pawn, new List <Pawn>());
                            }
                            PawnGenerator.pawnsBeingGenerated[i].PawnsGeneratedInTheMeantime.Add(pawn);
                        }
                        result = pawn;
                    }
                }
            }
            finally
            {
                PawnGenerator.pawnsBeingGenerated.RemoveLast <PawnGenerator.PawnGenerationStatus>();
            }
            return(result);
        }
        private static Pawn TryGenerateNewPawnInternal(ref PawnGenerationRequest request, out string error, bool ignoreScenarioRequirements, bool ignoreValidator)
        {
            error = null;
            Pawn pawn = (Pawn)ThingMaker.MakeThing(request.KindDef.race);

            pawnsBeingGenerated.Add(new PawnGenerationStatus(pawn, null));
            try
            {
                pawn.kindDef = request.KindDef;
                pawn.SetFactionDirect(request.Faction);
                PawnComponentsUtility.CreateInitialComponents(pawn);
                if (request.FixedGender.HasValue)
                {
                    pawn.gender = request.FixedGender.Value;
                }
                else if (pawn.RaceProps.hasGenders)
                {
                    if (Rand.Value < 0.5f)
                    {
                        pawn.gender = Gender.Male;
                    }
                    else
                    {
                        pawn.gender = Gender.Female;
                    }
                }
                else
                {
                    pawn.gender = Gender.None;
                }
                GenerateRandomAge(pawn, request);
                pawn.needs.SetInitialLevels();
                if (!request.Newborn && request.CanGeneratePawnRelations)
                {
                    GeneratePawnRelations(pawn, ref request);
                }
                if (pawn.RaceProps.Humanlike)
                {
                    Faction    faction;
                    FactionDef factionType = ((request.Faction != null) ? request.Faction.def : ((!Find.FactionManager.TryGetRandomNonColonyHumanlikeFaction_NewTemp(out faction, tryMedievalOrBetter: false, allowDefeated: true)) ? Faction.OfAncients.def : faction.def));
                    pawn.story.melanin   = (request.FixedMelanin.HasValue ? request.FixedMelanin.Value : PawnSkinColors.RandomMelanin(request.Faction));
                    pawn.story.crownType = ((Rand.Value < 0.5f) ? CrownType.Average : CrownType.Narrow);
                    pawn.story.hairColor = PawnHairColors.RandomHairColor(pawn.story.SkinColor, pawn.ageTracker.AgeBiologicalYears);
                    PawnBioAndNameGenerator.GiveAppropriateBioAndNameTo(pawn, request.FixedLastName, factionType);
                    if (pawn.story != null)
                    {
                        if (request.FixedBirthName != null)
                        {
                            pawn.story.birthLastName = request.FixedBirthName;
                        }
                        else if (pawn.Name is NameTriple)
                        {
                            pawn.story.birthLastName = ((NameTriple)pawn.Name).Last;
                        }
                    }
                    pawn.story.hairDef = PawnHairChooser.RandomHairDefFor(pawn, factionType);
                    GenerateTraits(pawn, request);
                    GenerateBodyType_NewTemp(pawn, request);
                    GenerateSkills(pawn);
                }
                if (pawn.RaceProps.Animal && request.Faction != null && request.Faction.IsPlayer)
                {
                    pawn.training.SetWantedRecursive(TrainableDefOf.Tameness, checkOn: true);
                    pawn.training.Train(TrainableDefOf.Tameness, null, complete: true);
                }
                GenerateInitialHediffs(pawn, request);
                if (!request.ForbidAnyTitle)
                {
                    RoyalTitleDef royalTitleDef = request.FixedTitle;
                    if (royalTitleDef == null)
                    {
                        if (request.KindDef.titleRequired != null)
                        {
                            royalTitleDef = request.KindDef.titleRequired;
                        }
                        else if (!request.KindDef.titleSelectOne.NullOrEmpty() && Rand.Chance(request.KindDef.royalTitleChance))
                        {
                            royalTitleDef = request.KindDef.titleSelectOne.RandomElementByWeight((RoyalTitleDef t) => t.commonality);
                        }
                    }
                    if (request.KindDef.minTitleRequired != null && (royalTitleDef == null || royalTitleDef.seniority < request.KindDef.minTitleRequired.seniority))
                    {
                        royalTitleDef = request.KindDef.minTitleRequired;
                    }
                    if (royalTitleDef != null)
                    {
                        Faction faction2 = ((request.Faction != null && request.Faction.def.HasRoyalTitles) ? request.Faction : Find.FactionManager.RandomRoyalFaction());
                        pawn.royalty.SetTitle(faction2, royalTitleDef, grantRewards: false);
                        if (request.Faction != null && !request.Faction.IsPlayer)
                        {
                            PurchasePermits(pawn, faction2);
                        }
                        int amount = 0;
                        if (royalTitleDef.GetNextTitle(faction2) != null)
                        {
                            amount = Rand.Range(0, royalTitleDef.GetNextTitle(faction2).favorCost - 1);
                        }
                        pawn.royalty.SetFavor_NewTemp(faction2, amount);
                        if (royalTitleDef.maxPsylinkLevel > 0)
                        {
                            Hediff_ImplantWithLevel hediff_ImplantWithLevel = HediffMaker.MakeHediff(HediffDefOf.PsychicAmplifier, pawn, pawn.health.hediffSet.GetBrain()) as Hediff_ImplantWithLevel;
                            pawn.health.AddHediff(hediff_ImplantWithLevel);
                            hediff_ImplantWithLevel.SetLevelTo(royalTitleDef.maxPsylinkLevel);
                        }
                    }
                }
                if (pawn.royalty != null)
                {
                    pawn.royalty.allowRoomRequirements    = request.KindDef.allowRoyalRoomRequirements;
                    pawn.royalty.allowApparelRequirements = request.KindDef.allowRoyalApparelRequirements;
                }
                if (pawn.workSettings != null && request.Faction != null && request.Faction.IsPlayer)
                {
                    pawn.workSettings.EnableAndInitialize();
                }
                if (request.Faction != null && pawn.RaceProps.Animal)
                {
                    pawn.GenerateNecessaryName();
                }
                if (Find.Scenario != null)
                {
                    Find.Scenario.Notify_NewPawnGenerating(pawn, request.Context);
                }
                if (!request.AllowDead && (pawn.Dead || pawn.Destroyed))
                {
                    DiscardGeneratedPawn(pawn);
                    error = "Generated dead pawn.";
                    return(null);
                }
                if (!request.AllowDowned && pawn.Downed)
                {
                    DiscardGeneratedPawn(pawn);
                    error = "Generated downed pawn.";
                    return(null);
                }
                if (request.MustBeCapableOfViolence && ((pawn.story != null && pawn.WorkTagIsDisabled(WorkTags.Violent)) || (pawn.RaceProps.ToolUser && !pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation))))
                {
                    DiscardGeneratedPawn(pawn);
                    error = "Generated pawn incapable of violence.";
                    return(null);
                }
                if (request.KindDef != null && !request.KindDef.skills.NullOrEmpty())
                {
                    List <SkillRange> skills = request.KindDef.skills;
                    for (int i = 0; i < skills.Count; i++)
                    {
                        if (pawn.skills.GetSkill(skills[i].Skill).TotallyDisabled)
                        {
                            error = "Generated pawn incapable of required skill: " + skills[i].Skill.defName;
                            return(null);
                        }
                    }
                }
                if (request.KindDef.requiredWorkTags != 0 && (pawn.CombinedDisabledWorkTags & request.KindDef.requiredWorkTags) != 0)
                {
                    DiscardGeneratedPawn(pawn);
                    error = "Generated pawn with disabled requiredWorkTags.";
                    return(null);
                }
                if (!ignoreScenarioRequirements && request.Context == PawnGenerationContext.PlayerStarter && Find.Scenario != null && !Find.Scenario.AllowPlayerStartingPawn(pawn, tryingToRedress: false, request))
                {
                    DiscardGeneratedPawn(pawn);
                    error = "Generated pawn doesn't meet scenario requirements.";
                    return(null);
                }
                if (!ignoreValidator && request.ValidatorPreGear != null && !request.ValidatorPreGear(pawn))
                {
                    DiscardGeneratedPawn(pawn);
                    error = "Generated pawn didn't pass validator check (pre-gear).";
                    return(null);
                }
                if (!request.Newborn)
                {
                    GenerateGearFor(pawn, request);
                }
                if (!ignoreValidator && request.ValidatorPostGear != null && !request.ValidatorPostGear(pawn))
                {
                    DiscardGeneratedPawn(pawn);
                    error = "Generated pawn didn't pass validator check (post-gear).";
                    return(null);
                }
                for (int j = 0; j < pawnsBeingGenerated.Count - 1; j++)
                {
                    if (pawnsBeingGenerated[j].PawnsGeneratedInTheMeantime == null)
                    {
                        pawnsBeingGenerated[j] = new PawnGenerationStatus(pawnsBeingGenerated[j].Pawn, new List <Pawn>());
                    }
                    pawnsBeingGenerated[j].PawnsGeneratedInTheMeantime.Add(pawn);
                }
                return(pawn);
            }
            finally
            {
                pawnsBeingGenerated.RemoveLast();
            }
        }
 private static bool IsValidCandidateToRedress(Pawn pawn, PawnGenerationRequest request)
 {
     if (pawn.def != request.KindDef.race)
     {
         return(false);
     }
     if (!request.WorldPawnFactionDoesntMatter && pawn.Faction != request.Faction)
     {
         return(false);
     }
     if (!request.AllowDead && (pawn.Dead || pawn.Destroyed))
     {
         return(false);
     }
     if (!request.AllowDowned && pawn.Downed)
     {
         return(false);
     }
     if (pawn.health.hediffSet.BleedRateTotal > 0.001f)
     {
         return(false);
     }
     if (!request.CanGeneratePawnRelations && pawn.RaceProps.IsFlesh && pawn.relations.RelatedToAnyoneOrAnyoneRelatedToMe)
     {
         return(false);
     }
     if (!request.AllowGay && pawn.RaceProps.Humanlike && pawn.story.traits.HasTrait(TraitDefOf.Gay))
     {
         return(false);
     }
     if (request.ValidatorPreGear != null && !request.ValidatorPreGear(pawn))
     {
         return(false);
     }
     if (request.ValidatorPostGear != null && !request.ValidatorPostGear(pawn))
     {
         return(false);
     }
     if (request.FixedBiologicalAge.HasValue && pawn.ageTracker.AgeBiologicalYearsFloat != request.FixedBiologicalAge)
     {
         return(false);
     }
     if (request.FixedChronologicalAge.HasValue && (float)pawn.ageTracker.AgeChronologicalYears != request.FixedChronologicalAge)
     {
         return(false);
     }
     if (request.FixedGender.HasValue && pawn.gender != request.FixedGender)
     {
         return(false);
     }
     if (request.FixedLastName != null && ((NameTriple)pawn.Name).Last != request.FixedLastName)
     {
         return(false);
     }
     if (request.FixedMelanin.HasValue && pawn.story != null && pawn.story.melanin != request.FixedMelanin)
     {
         return(false);
     }
     if (request.Context == PawnGenerationContext.PlayerStarter && Find.Scenario != null && !Find.Scenario.AllowPlayerStartingPawn(pawn, true, request))
     {
         return(false);
     }
     if (request.MustBeCapableOfViolence)
     {
         if (pawn.story != null && pawn.story.WorkTagIsDisabled(WorkTags.Violent))
         {
             return(false);
         }
         if (pawn.RaceProps.ToolUser && !pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation))
         {
             return(false);
         }
     }
     return(true);
 }
        private static bool IsValidCandidateToRedress(Pawn pawn, PawnGenerationRequest request)
        {
            if (pawn.def != request.KindDef.race)
            {
                return(false);
            }
            if (!request.WorldPawnFactionDoesntMatter && pawn.Faction != request.Faction)
            {
                return(false);
            }
            if (!request.AllowDead)
            {
                if (pawn.Dead || pawn.Destroyed)
                {
                    return(false);
                }
                if (pawn.health.hediffSet.GetBrain() == null)
                {
                    return(false);
                }
            }
            if (!request.AllowDowned && pawn.Downed)
            {
                return(false);
            }
            if (pawn.health.hediffSet.BleedRateTotal > 0.001f)
            {
                return(false);
            }
            if (!request.CanGeneratePawnRelations && pawn.RaceProps.IsFlesh && pawn.relations.RelatedToAnyoneOrAnyoneRelatedToMe)
            {
                return(false);
            }
            if (!request.AllowGay && pawn.RaceProps.Humanlike && pawn.story.traits.HasTrait(TraitDefOf.Gay))
            {
                return(false);
            }
            if (!request.AllowAddictions && AddictionUtility.AddictedToAnything(pawn))
            {
                return(false);
            }
            if (request.ProhibitedTraits != null && request.ProhibitedTraits.Any((TraitDef t) => pawn.story.traits.HasTrait(t)))
            {
                return(false);
            }
            List <SkillRange> skills = request.KindDef.skills;

            if (skills != null)
            {
                for (int i = 0; i < skills.Count; i++)
                {
                    SkillRecord skill = pawn.skills.GetSkill(skills[i].Skill);
                    if (skill.TotallyDisabled)
                    {
                        return(false);
                    }
                    if (skill.Level < skills[i].Range.min || skill.Level > skills[i].Range.max)
                    {
                        return(false);
                    }
                }
            }
            if (request.ForcedTraits != null)
            {
                foreach (TraitDef forcedTrait in request.ForcedTraits)
                {
                    if (!pawn.story.traits.HasTrait(forcedTrait))
                    {
                        return(false);
                    }
                }
            }
            if (request.ValidatorPreGear != null && !request.ValidatorPreGear(pawn))
            {
                return(false);
            }
            if (request.ValidatorPostGear != null && !request.ValidatorPostGear(pawn))
            {
                return(false);
            }
            if (request.FixedBiologicalAge.HasValue && pawn.ageTracker.AgeBiologicalYearsFloat != request.FixedBiologicalAge)
            {
                return(false);
            }
            if (request.FixedChronologicalAge.HasValue && (float)pawn.ageTracker.AgeChronologicalYears != request.FixedChronologicalAge)
            {
                return(false);
            }
            if (request.FixedGender.HasValue && pawn.gender != request.FixedGender)
            {
                return(false);
            }
            if (request.FixedLastName != null && (!(pawn.Name is NameTriple) || ((NameTriple)pawn.Name).Last != request.FixedLastName))
            {
                return(false);
            }
            if (request.FixedMelanin.HasValue && pawn.story != null && pawn.story.melanin != request.FixedMelanin)
            {
                return(false);
            }
            if (request.FixedTitle != null && (pawn.royalty == null || !pawn.royalty.HasTitle(request.FixedTitle)))
            {
                return(false);
            }
            if (request.KindDef.minTitleRequired != null)
            {
                if (pawn.royalty == null)
                {
                    return(false);
                }
                RoyalTitleDef royalTitleDef = pawn.royalty.MainTitle();
                if (royalTitleDef == null || royalTitleDef.seniority < request.KindDef.minTitleRequired.seniority)
                {
                    return(false);
                }
            }
            if (request.Context == PawnGenerationContext.PlayerStarter && Find.Scenario != null && !Find.Scenario.AllowPlayerStartingPawn(pawn, tryingToRedress: true, request))
            {
                return(false);
            }
            if (request.MustBeCapableOfViolence)
            {
                if (pawn.WorkTagIsDisabled(WorkTags.Violent))
                {
                    return(false);
                }
                if (pawn.RaceProps.ToolUser && !pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation))
                {
                    return(false);
                }
            }
            if (request.RedressValidator != null && !request.RedressValidator(pawn))
            {
                return(false);
            }
            if (request.KindDef.requiredWorkTags != 0 && pawn.kindDef != request.KindDef && (pawn.CombinedDisabledWorkTags & request.KindDef.requiredWorkTags) != 0)
            {
                return(false);
            }
            return(true);
        }