public CustomPawn LoadPawn(SaveRecordPawnV3 record)
        {
            PawnKindDef pawnKindDef = null;

            if (record.pawnKindDef != null)
            {
                pawnKindDef = DefDatabase <PawnKindDef> .GetNamedSilentFail(record.pawnKindDef);

                if (pawnKindDef == null)
                {
                    Log.Warning("Prepare Carefully could not find the pawn kind definition for the saved character: \"" + record.pawnKindDef + "\"");
                    return(null);
                }
            }

            ThingDef pawnThingDef = ThingDefOf.Human;

            if (record.thingDef != null)
            {
                ThingDef thingDef = DefDatabase <ThingDef> .GetNamedSilentFail(record.thingDef);

                if (thingDef != null)
                {
                    pawnThingDef = thingDef;
                }
            }

            Pawn source;

            if (pawnKindDef != null)
            {
                source = new Randomizer().GenerateKindOfColonist(pawnKindDef);
            }
            else
            {
                source = new Randomizer().GenerateColonist();
            }
            source.health.Reset();

            CustomPawn pawn = new CustomPawn(source);

            if (pawn.Id == null)
            {
                pawn.GenerateId();
            }
            else
            {
                pawn.Id = record.id;
            }

            pawn.Gender = record.gender;
            if (record.age > 0)
            {
                pawn.ChronologicalAge = record.age;
                pawn.BiologicalAge    = record.age;
            }
            if (record.chronologicalAge > 0)
            {
                pawn.ChronologicalAge = record.chronologicalAge;
            }
            if (record.biologicalAge > 0)
            {
                pawn.BiologicalAge = record.biologicalAge;
            }

            pawn.FirstName = record.firstName;
            pawn.NickName  = record.nickName;
            pawn.LastName  = record.lastName;

            HairDef h = FindHairDef(record.hairDef);

            if (h != null)
            {
                pawn.HairDef = h;
            }
            else
            {
                Log.Warning("Could not load hair definition \"" + record.hairDef + "\"");
                Failed = true;
            }

            pawn.HeadGraphicPath = record.headGraphicPath;
            pawn.SetColor(PawnLayers.Hair, record.hairColor);

            if (record.melanin >= 0.0f)
            {
                pawn.MelaninLevel = record.melanin;
            }
            else
            {
                pawn.MelaninLevel = PawnColorUtils.FindMelaninValueFromColor(record.skinColor);
            }
            // Set the skin color (only for Alien Races).
            if (pawn.AlienRace != null)
            {
                pawn.SkinColor = record.skinColor;
            }

            Backstory backstory = FindBackstory(record.childhood);

            if (backstory != null)
            {
                pawn.Childhood = backstory;
            }
            else
            {
                Log.Warning("Could not load childhood backstory definition \"" + record.childhood + "\"");
                Failed = true;
            }
            if (record.adulthood != null)
            {
                backstory = FindBackstory(record.adulthood);
                if (backstory != null)
                {
                    pawn.Adulthood = backstory;
                }
                else
                {
                    Log.Warning("Could not load adulthood backstory definition \"" + record.adulthood + "\"");
                    Failed = true;
                }
            }

            // Get the body type from the save record.  If there's no value in the save, then assign the
            // default body type from the pawn's backstories.
            BodyType?bodyType = null;

            try {
                bodyType = (BodyType)Enum.Parse(typeof(BodyType), record.bodyType);
            }
            catch (Exception) {
            }
            if (!bodyType.HasValue)
            {
                if (pawn.Adulthood != null)
                {
                    bodyType = pawn.Adulthood.BodyTypeFor(pawn.Gender);
                }
                else
                {
                    bodyType = pawn.Childhood.BodyTypeFor(pawn.Gender);
                }
            }
            if (bodyType.HasValue)
            {
                pawn.BodyType = bodyType.Value;
            }

            pawn.ClearTraits();
            for (int i = 0; i < record.traitNames.Count; i++)
            {
                string traitName = record.traitNames[i];
                Trait  trait     = FindTrait(traitName, record.traitDegrees[i]);
                if (trait != null)
                {
                    pawn.AddTrait(trait);
                }
                else
                {
                    Log.Warning("Could not load trait definition \"" + traitName + "\"");
                    Failed = true;
                }
            }

            for (int i = 0; i < record.skillNames.Count; i++)
            {
                string name = record.skillNames[i];
                if (name == "Research")
                {
                    name = "Intellectual";
                }
                SkillDef def = FindSkillDef(pawn.Pawn, name);
                if (def == null)
                {
                    Log.Warning("Could not load skill definition \"" + name + "\"");
                    Failed = true;
                    continue;
                }
                pawn.currentPassions[def]  = record.passions[i];
                pawn.originalPassions[def] = record.passions[i];
                pawn.SetOriginalSkillLevel(def, record.skillValues[i]);
                pawn.SetUnmodifiedSkillLevel(def, record.skillValues[i]);
            }
            if (record.originalPassions != null && record.originalPassions.Count == record.skillNames.Count)
            {
                for (int i = 0; i < record.skillNames.Count; i++)
                {
                    string   name = record.skillNames[i];
                    SkillDef def  = FindSkillDef(pawn.Pawn, name);
                    if (def == null)
                    {
                        Log.Warning("Could not load skill definition \"" + name + "\"");
                        Failed = true;
                        continue;
                    }
                    //pawn.originalPassions[def] = record.originalPassions[i];
                }
            }

            for (int i = 0; i < PawnLayers.Count; i++)
            {
                if (PawnLayers.IsApparelLayer(i))
                {
                    pawn.SetSelectedApparel(i, null);
                    pawn.SetSelectedStuff(i, null);
                }
            }
            for (int i = 0; i < record.apparelLayers.Count; i++)
            {
                int      layer = record.apparelLayers[i];
                ThingDef def   = DefDatabase <ThingDef> .GetNamedSilentFail(record.apparel[i]);

                if (def == null)
                {
                    Log.Warning("Could not load thing definition for apparel \"" + record.apparel[i] + "\"");
                    Failed = true;
                    continue;
                }
                ThingDef stuffDef = null;
                if (!string.IsNullOrEmpty(record.apparelStuff[i]))
                {
                    stuffDef = DefDatabase <ThingDef> .GetNamedSilentFail(record.apparelStuff[i]);

                    if (stuffDef == null)
                    {
                        Log.Warning("Could not load stuff definition \"" + record.apparelStuff[i] + "\" for apparel \"" + record.apparel[i] + "\"");
                        Failed = true;
                        continue;
                    }
                }
                pawn.SetSelectedApparel(layer, def);
                pawn.SetSelectedStuff(layer, stuffDef);
                pawn.SetColor(layer, record.apparelColors[i]);
            }

            OptionsHealth healthOptions = PrepareCarefully.Instance.Providers.Health.GetOptions(pawn);

            for (int i = 0; i < record.implants.Count; i++)
            {
                SaveRecordImplantV3 implantRecord  = record.implants[i];
                UniqueBodyPart      uniqueBodyPart = healthOptions.FindBodyPartByName(implantRecord.bodyPart, implantRecord.bodyPartIndex != null ? implantRecord.bodyPartIndex.Value : 0);
                if (uniqueBodyPart == null)
                {
                    Log.Warning("Prepare Carefully could not add the implant because it could not find the needed body part \"" + implantRecord.bodyPart + "\""
                                + (implantRecord.bodyPartIndex != null ? " with index " + implantRecord.bodyPartIndex : ""));
                    Failed = true;
                    continue;
                }
                BodyPartRecord bodyPart = uniqueBodyPart.Record;
                if (implantRecord.recipe != null)
                {
                    RecipeDef recipeDef = FindRecipeDef(implantRecord.recipe);
                    if (recipeDef == null)
                    {
                        Log.Warning("Prepare Carefully could not add the implant because it could not find the recipe definition \"" + implantRecord.recipe + "\"");
                        Failed = true;
                        continue;
                    }
                    bool found = false;
                    foreach (var p in recipeDef.appliedOnFixedBodyParts)
                    {
                        if (p.defName.Equals(bodyPart.def.defName))
                        {
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        Log.Warning("Prepare carefully could not apply the saved implant recipe \"" + implantRecord.recipe + "\" to the body part \"" + bodyPart.def.defName + "\".  Recipe does not support that part.");
                        Failed = true;
                        continue;
                    }
                    Implant implant = new Implant();
                    implant.BodyPartRecord = bodyPart;
                    implant.recipe         = recipeDef;
                    implant.label          = implant.Label;
                    pawn.AddImplant(implant);
                }
            }

            foreach (var injuryRecord in record.injuries)
            {
                HediffDef def = DefDatabase <HediffDef> .GetNamedSilentFail(injuryRecord.hediffDef);

                if (def == null)
                {
                    Log.Warning("Prepare Carefully could not add the injury because it could not find the hediff definition \"" + injuryRecord.hediffDef + "\"");
                    Failed = true;
                    continue;
                }
                InjuryOption option = healthOptions.FindInjuryOptionByHediffDef(def);
                if (option == null)
                {
                    Log.Warning("Prepare Carefully could not add the injury because it could not find a matching injury option for the saved hediff \"" + injuryRecord.hediffDef + "\"");
                    Failed = true;
                    continue;
                }
                BodyPartRecord bodyPart = null;
                if (injuryRecord.bodyPart != null)
                {
                    UniqueBodyPart uniquePart = healthOptions.FindBodyPartByName(injuryRecord.bodyPart,
                                                                                 injuryRecord.bodyPartIndex != null ? injuryRecord.bodyPartIndex.Value : 0);
                    if (uniquePart == null)
                    {
                        Log.Warning("Prepare Carefully could not add the injury because it could not find the needed body part \"" + injuryRecord.bodyPart + "\""
                                    + (injuryRecord.bodyPartIndex != null ? " with index " + injuryRecord.bodyPartIndex : ""));
                        Failed = true;
                        continue;
                    }
                    bodyPart = uniquePart.Record;
                }
                Injury injury = new Injury();
                injury.Option         = option;
                injury.BodyPartRecord = bodyPart;
                if (injuryRecord.severity != null)
                {
                    injury.Severity = injuryRecord.Severity;
                }
                if (injuryRecord.painFactor != null)
                {
                    injury.PainFactor = injuryRecord.PainFactor;
                }
                pawn.AddInjury(injury);
            }

            pawn.CopySkillsAndPassionsToPawn();
            pawn.ClearPawnCaches();

            return(pawn);
        }
        public CustomPawn LoadPawn(SaveRecordPawnV3 record)
        {
            PawnKindDef pawnKindDef = null;

            if (record.pawnKindDef != null)
            {
                pawnKindDef = DefDatabase <PawnKindDef> .GetNamedSilentFail(record.pawnKindDef);
            }

            ThingDef pawnThingDef = ThingDefOf.Human;

            if (record.thingDef != null)
            {
                ThingDef thingDef = DefDatabase <ThingDef> .GetNamedSilentFail(record.thingDef);

                if (thingDef != null)
                {
                    pawnThingDef = thingDef;
                }
            }

            Pawn source;

            if (pawnKindDef != null)
            {
                source = new Randomizer().GenerateKindOfColonist(pawnKindDef);
            }
            else
            {
                source = new Randomizer().GenerateColonist();
            }

            CustomPawn pawn = new CustomPawn(source);

            pawn.Gender = record.gender;
            if (record.age > 0)
            {
                pawn.ChronologicalAge = record.age;
                pawn.BiologicalAge    = record.age;
            }
            if (record.chronologicalAge > 0)
            {
                pawn.ChronologicalAge = record.chronologicalAge;
            }
            if (record.biologicalAge > 0)
            {
                pawn.BiologicalAge = record.biologicalAge;
            }

            pawn.FirstName = record.firstName;
            pawn.NickName  = record.nickName;
            pawn.LastName  = record.lastName;

            HairDef h = FindHairDef(record.hairDef);

            if (h != null)
            {
                pawn.HairDef = h;
            }
            else
            {
                Log.Warning("Could not load hair definition \"" + record.hairDef + "\"");
                Failed = true;
            }

            pawn.HeadGraphicPath = record.headGraphicPath;
            pawn.SetColor(PawnLayers.Hair, record.hairColor);

            if (record.melanin >= 0.0f)
            {
                pawn.MelaninLevel = record.melanin;
            }
            else
            {
                pawn.MelaninLevel = PawnColorUtils.FindMelaninValueFromColor(record.skinColor);
            }

            Backstory backstory = FindBackstory(record.childhood);

            if (backstory != null)
            {
                pawn.Childhood = backstory;
            }
            else
            {
                Log.Warning("Could not load childhood backstory definition \"" + record.childhood + "\"");
                Failed = true;
            }
            if (record.adulthood != null)
            {
                backstory = FindBackstory(record.adulthood);
                if (backstory != null)
                {
                    pawn.Adulthood = backstory;
                }
                else
                {
                    Log.Warning("Could not load adulthood backstory definition \"" + record.adulthood + "\"");
                    Failed = true;
                }
            }

            // Get the body type from the save record.  If there's no value in the save, then assign the
            // default body type from the pawn's backstories.
            BodyType?bodyType = null;

            try {
                bodyType = (BodyType)Enum.Parse(typeof(BodyType), record.bodyType);
            }
            catch (Exception) {
                Log.Warning("Invalid body type value \"" + record.bodyType + "\"");
            }
            if (!bodyType.HasValue)
            {
                if (pawn.Adulthood != null)
                {
                    bodyType = pawn.Adulthood.BodyTypeFor(pawn.Gender);
                }
                else
                {
                    bodyType = pawn.Childhood.BodyTypeFor(pawn.Gender);
                }
            }
            if (bodyType.HasValue)
            {
                pawn.BodyType = bodyType.Value;
            }

            int traitCount = pawn.Traits.Count();

            for (int i = 0; i < traitCount; i++)
            {
                pawn.ClearTrait(i);
            }
            for (int i = 0; i < record.traitNames.Count; i++)
            {
                string traitName = record.traitNames[i];
                if (i >= traitCount)
                {
                    break;
                }
                Trait trait = FindTrait(traitName, record.traitDegrees[i]);
                if (trait != null)
                {
                    pawn.SetTrait(i, trait);
                }
                else
                {
                    Log.Warning("Could not load trait definition \"" + traitName + "\"");
                    Failed = true;
                }
            }

            for (int i = 0; i < record.skillNames.Count; i++)
            {
                string   name = record.skillNames[i];
                SkillDef def  = FindSkillDef(pawn.Pawn, name);
                if (def == null)
                {
                    Log.Warning("Could not load skill definition \"" + name + "\"");
                    Failed = true;
                    continue;
                }
                pawn.currentPassions[def]  = record.passions[i];
                pawn.originalPassions[def] = record.passions[i];
                pawn.SetOriginalSkillLevel(def, record.skillValues[i]);
                pawn.SetUnmodifiedSkillLevel(def, record.skillValues[i]);
            }
            if (record.originalPassions != null && record.originalPassions.Count == record.skillNames.Count)
            {
                for (int i = 0; i < record.skillNames.Count; i++)
                {
                    string   name = record.skillNames[i];
                    SkillDef def  = FindSkillDef(pawn.Pawn, name);
                    if (def == null)
                    {
                        Log.Warning("Could not load skill definition \"" + name + "\"");
                        Failed = true;
                        continue;
                    }
                    //pawn.originalPassions[def] = record.originalPassions[i];
                }
            }

            for (int i = 0; i < PawnLayers.Count; i++)
            {
                if (PawnLayers.IsApparelLayer(i))
                {
                    pawn.SetSelectedApparel(i, null);
                    pawn.SetSelectedStuff(i, null);
                }
            }
            for (int i = 0; i < record.apparelLayers.Count; i++)
            {
                int      layer = record.apparelLayers[i];
                ThingDef def   = DefDatabase <ThingDef> .GetNamedSilentFail(record.apparel[i]);

                if (def == null)
                {
                    Log.Warning("Could not load thing definition for apparel \"" + record.apparel[i] + "\"");
                    Failed = true;
                    continue;
                }
                ThingDef stuffDef = null;
                if (!string.IsNullOrEmpty(record.apparelStuff[i]))
                {
                    stuffDef = DefDatabase <ThingDef> .GetNamedSilentFail(record.apparelStuff[i]);

                    if (stuffDef == null)
                    {
                        Log.Warning("Could not load stuff definition \"" + record.apparelStuff[i] + "\" for apparel \"" + record.apparel[i] + "\"");
                        Failed = true;
                        continue;
                    }
                }
                pawn.SetSelectedApparel(layer, def);
                pawn.SetSelectedStuff(layer, stuffDef);
                pawn.SetColor(layer, record.apparelColors[i]);
            }

            for (int i = 0; i < record.implants.Count; i++)
            {
                SaveRecordImplantV3 implantRecord = record.implants[i];
                BodyPartRecord      bodyPart      = PrepareCarefully.Instance.HealthManager.ImplantManager.FindReplaceableBodyPartByName(pawn.Pawn, implantRecord.bodyPart);
                if (bodyPart == null)
                {
                    Log.Warning("Could not find replaceable body part definition \"" + implantRecord.bodyPart + "\"");
                    Failed = true;
                    continue;
                }
                if (implantRecord.recipe != null)
                {
                    RecipeDef recipeDef = FindRecipeDef(implantRecord.recipe);
                    if (recipeDef == null)
                    {
                        Log.Warning("Could not find recipe definition \"" + implantRecord.recipe + "\"");
                        Failed = true;
                        continue;
                    }
                    bool found = false;
                    foreach (var p in recipeDef.appliedOnFixedBodyParts)
                    {
                        if (p.defName.Equals(bodyPart.def.defName))
                        {
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        Log.Warning("Body part \"" + bodyPart.def.defName + "\" does not match recipe used to replace it");
                        Failed = true;
                        continue;
                    }
                    Implant implant = new Implant();
                    implant.BodyPartRecord = bodyPart;
                    implant.recipe         = recipeDef;
                    implant.label          = implant.Label;
                    pawn.AddImplant(implant);
                }
            }

            foreach (var injuryRecord in record.injuries)
            {
                HediffDef def = DefDatabase <HediffDef> .GetNamedSilentFail(injuryRecord.hediffDef);

                if (def == null)
                {
                    Log.Warning("Could not find hediff definition \"" + injuryRecord.hediffDef + "\"");
                    Failed = true;
                    continue;
                }
                InjuryOption option = PrepareCarefully.Instance.HealthManager.InjuryManager.FindOptionByHediffDef(def);
                if (option == null)
                {
                    Log.Warning("Could not find injury option for \"" + injuryRecord.hediffDef + "\"");
                    Failed = true;
                    continue;
                }
                BodyPartRecord bodyPart = null;
                if (injuryRecord.bodyPart != null)
                {
                    bodyPart = PrepareCarefully.Instance.HealthManager.FirstBodyPartRecord(pawn, injuryRecord.bodyPart);
                    if (bodyPart == null)
                    {
                        Log.Warning("Could not find body part \"" + injuryRecord.bodyPart + "\"");
                        Failed = true;
                        continue;
                    }
                }
                Injury injury = new Injury();
                injury.Option         = option;
                injury.BodyPartRecord = bodyPart;
                if (injuryRecord.severity != null)
                {
                    injury.Severity = injuryRecord.Severity;
                }
                pawn.AddInjury(injury);
            }

            pawn.RandomInjuries  = record.randomInjuries;
            pawn.RandomRelations = record.randomRelations;
            pawn.ClearCachedAbilities();
            pawn.ClearCachedLifeStage();

            return(pawn);
        }