public CustomPawn Load(PrepareCarefully loadout, string name) { SaveRecordPawnV4 pawnRecord = new SaveRecordPawnV4(); string modString = ""; string version = ""; try { Scribe.loader.InitLoading(ColonistFiles.FilePathForSavedColonist(name)); Scribe_Values.Look <string>(ref version, "version", "unknown", false); Scribe_Values.Look <string>(ref modString, "mods", "", false); try { Scribe_Deep.Look <SaveRecordPawnV4>(ref pawnRecord, "pawn", null); } catch (Exception e) { Messages.Message(modString, MessageTypeDefOf.SilentInput); Messages.Message("EdB.PC.Dialog.PawnPreset.Error.Failed".Translate(), MessageTypeDefOf.RejectInput); Logger.Warning(e.ToString()); Logger.Warning("Colonist was created with the following mods: " + modString); return(null); } } catch (Exception e) { Logger.Error("Failed to load preset file"); throw e; } finally { PresetLoader.ClearSaveablesAndCrossRefs(); } if (pawnRecord == null) { Messages.Message(modString, MessageTypeDefOf.SilentInput); Messages.Message("EdB.PC.Dialog.PawnPreset.Error.Failed".Translate(), MessageTypeDefOf.RejectInput); Logger.Warning("Colonist was created with the following mods: " + modString); return(null); } PresetLoaderVersion4 loader = new PresetLoaderVersion4(); CustomPawn loadedPawn = loader.LoadPawn(pawnRecord); if (loadedPawn != null) { CustomPawn idConflictPawn = PrepareCarefully.Instance.Pawns.FirstOrDefault((CustomPawn p) => { return(p.Id == loadedPawn.Id); }); if (idConflictPawn != null) { loadedPawn.GenerateId(); } return(loadedPawn); } else { loadout.State.AddError(modString); loadout.State.AddError("EdB.PC.Dialog.Preset.Error.NoCharacter".Translate()); Logger.Warning("Preset was created with the following mods: " + modString); return(null); } }
// // Static Methods // public static void SaveToFile(CustomPawn customPawn, string colonistName) { try { Scribe.saver.InitSaving(ColonistFiles.FilePathForSavedColonist(colonistName), "character"); string versionStringFull = "4"; Scribe_Values.Look <string>(ref versionStringFull, "version", null, false); string modString = GenText.ToCommaList(Enumerable.Select <ModContentPack, string>(LoadedModManager.RunningMods, (Func <ModContentPack, string>)(mod => mod.Name)), true); Scribe_Values.Look <string>(ref modString, "mods", null, false); SaveRecordPawnV4 pawn = new SaveRecordPawnV4(customPawn); Scribe_Deep.Look <SaveRecordPawnV4>(ref pawn, "pawn"); } catch (Exception e) { Log.Error("Failed to save preset file"); throw e; } finally { Scribe.saver.FinalizeSaving(); Scribe.mode = LoadSaveMode.Inactive; } }
public CustomPawn LoadPawn(SaveRecordPawnV4 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; } } PawnGenerationRequestWrapper generationRequest = new PawnGenerationRequestWrapper() { FixedBiologicalAge = record.biologicalAge, FixedChronologicalAge = record.chronologicalAge, FixedGender = record.gender }; if (pawnKindDef != null) { generationRequest.KindDef = pawnKindDef; } Pawn source = PawnGenerator.GeneratePawn(generationRequest.Request); if (source.health != null) { source.health.Reset(); } CustomPawn pawn = new CustomPawn(source); if (record.id == null) { pawn.GenerateId(); } else { pawn.Id = record.id; } if (record.type != null) { try { pawn.Type = (CustomPawnType)Enum.Parse(typeof(CustomPawnType), record.type); } catch (Exception) { pawn.Type = CustomPawnType.Colonist; } } else { pawn.Type = CustomPawnType.Colonist; } 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; if (record.originalFactionDef != null) { pawn.OriginalFactionDef = DefDatabase <FactionDef> .GetNamedSilentFail(record.originalFactionDef); } pawn.OriginalKindDef = pawnKindDef; if (pawn.Type == CustomPawnType.World) { if (record.faction != null) { if (record.faction.def != null) { FactionDef factionDef = DefDatabase <FactionDef> .GetNamedSilentFail(record.faction.def); if (factionDef != null) { bool randomFaction = false; if (record.faction.index != null) { CustomFaction customFaction = null; if (!record.faction.leader) { customFaction = PrepareCarefully.Instance.Providers.Factions.FindCustomFactionByIndex(factionDef, record.faction.index.Value); } else { customFaction = PrepareCarefully.Instance.Providers.Factions.FindCustomFactionWithLeaderOptionByIndex(factionDef, record.faction.index.Value); } if (customFaction != null) { pawn.Faction = customFaction; } else { Log.Warning("Prepare Carefully could not place at least one preset character into a saved faction because there were not enough available factions of that type in the world"); randomFaction = true; } } else { randomFaction = true; } if (randomFaction) { CustomFaction customFaction = PrepareCarefully.Instance.Providers.Factions.FindRandomCustomFactionByDef(factionDef); if (customFaction != null) { pawn.Faction = customFaction; } } } else { Log.Warning("Prepare Carefully could not place at least one preset character into a saved faction because that faction is not available in the world"); } } } } 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; if (pawn.Pawn.story != null) { pawn.Pawn.story.hairColor = record.hairColor; } if (record.melanin >= 0.0f) { pawn.MelaninLevel = record.melanin; } else { pawn.MelaninLevel = PawnColorUtils.FindMelaninValueFromColor(record.skinColor); } // Set the skin color for Alien Races and alien comp values. if (pawn.AlienRace != null) { pawn.SkinColor = record.skinColor; if (record.alien != null) { ThingComp alienComp = ProviderAlienRaces.FindAlienCompForPawn(pawn.Pawn); if (alienComp != null) { ProviderAlienRaces.SetCrownTypeOnComp(alienComp, record.alien.crownType); ProviderAlienRaces.SetSkinColorOnComp(alienComp, record.alien.skinColor); ProviderAlienRaces.SetSkinColorSecondOnComp(alienComp, record.alien.skinColorSecond); ProviderAlienRaces.SetHairColorSecondOnComp(alienComp, record.alien.hairColorSecond); } } } 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; } } BodyTypeDef bodyType = null; try { bodyType = DefDatabase <BodyTypeDef> .GetNamedSilentFail(record.bodyType); } catch (Exception) { } if (bodyType == null) { if (pawn.Adulthood != null) { bodyType = pawn.Adulthood.BodyTypeFor(pawn.Gender); } else { bodyType = pawn.Childhood.BodyTypeFor(pawn.Gender); } } if (bodyType != null) { pawn.BodyType = bodyType; } 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; } } foreach (var skill in record.skills) { SkillDef def = FindSkillDef(pawn.Pawn, skill.name); if (def == null) { Log.Warning("Could not load skill definition \"" + skill.name + "\" from saved preset"); Failed = true; continue; } pawn.currentPassions[def] = skill.passion; pawn.originalPassions[def] = skill.passion; pawn.SetOriginalSkillLevel(def, skill.value); pawn.SetUnmodifiedSkillLevel(def, skill.value); } foreach (var layer in PrepareCarefully.Instance.Providers.PawnLayers.GetLayersForPawn(pawn)) { if (layer.Apparel) { pawn.SetSelectedApparel(layer, null); pawn.SetSelectedStuff(layer, null); } } List <PawnLayer> apparelLayers = PrepareCarefully.Instance.Providers.PawnLayers.GetLayersForPawn(pawn).FindAll((layer) => { return(layer.Apparel); }); foreach (var apparelRecord in record.apparel) { // Find the pawn layer for the saved apparel record. PawnLayer layer = apparelLayers.FirstOrDefault((apparelLayer) => { return(apparelLayer.Name == apparelRecord.layer); }); if (layer == null) { Log.Warning("Could not find a matching pawn layer for the saved apparel \"" + apparelRecord.layer + "\""); Failed = true; continue; } if (apparelRecord.apparel.NullOrEmpty()) { Log.Warning("Saved apparel entry for layer \"" + apparelRecord.layer + "\" had an empty apparel def"); Failed = true; continue; } // Set the defaults. pawn.SetSelectedApparel(layer, null); pawn.SetSelectedStuff(layer, null); pawn.SetColor(layer, Color.white); ThingDef def = DefDatabase <ThingDef> .GetNamedSilentFail(apparelRecord.apparel); if (def == null) { Log.Warning("Could not load thing definition for apparel \"" + apparelRecord.apparel + "\""); Failed = true; continue; } ThingDef stuffDef = null; if (!string.IsNullOrEmpty(apparelRecord.stuff)) { stuffDef = DefDatabase <ThingDef> .GetNamedSilentFail(apparelRecord.stuff); if (stuffDef == null) { Log.Warning("Could not load stuff definition \"" + apparelRecord.stuff + "\" for apparel \"" + apparelRecord.apparel + "\""); Failed = true; continue; } } pawn.SetSelectedApparel(layer, def); pawn.SetSelectedStuff(layer, stuffDef); pawn.SetColor(layer, apparelRecord.color); } 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) { uniqueBodyPart = FindReplacementBodyPart(healthOptions, implantRecord.bodyPart); } 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) { uniquePart = FindReplacementBodyPart(healthOptions, injuryRecord.bodyPart); } 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 Load(PrepareCarefully loadout, string name) { SaveRecordPawnV4 pawnRecord = new SaveRecordPawnV4(); string modString = ""; string version = ""; try { Scribe.loader.InitLoading(ColonistFiles.FilePathForSavedColonist(name)); Scribe_Values.Look <string>(ref version, "version", "unknown", false); Scribe_Values.Look <string>(ref modString, "mods", "", false); try { Scribe_Deep.Look <SaveRecordPawnV4>(ref pawnRecord, "pawn", null); } catch (Exception e) { Messages.Message(modString, MessageTypeDefOf.SilentInput); Messages.Message("EdB.PC.Dialog.PawnPreset.Error.Failed".Translate(), MessageTypeDefOf.RejectInput); Log.Warning(e.ToString()); Log.Warning("Colonist was created with the following mods: " + modString); return(null); } } catch (Exception e) { Log.Error("Failed to load preset file"); throw e; } finally { // I don't fully understand how these cross-references and saveables are resolved, but // if we don't clear them out, we get null pointer exceptions. HashSet <IExposable> saveables = (HashSet <IExposable>)(typeof(PostLoadIniter).GetField("saveablesToPostLoad", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(Scribe.loader.initer)); saveables.Clear(); List <IExposable> crossReferencingExposables = (List <IExposable>)(typeof(CrossRefHandler).GetField("crossReferencingExposables", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(Scribe.loader.crossRefs)); crossReferencingExposables.Clear(); Scribe.loader.FinalizeLoading(); } if (pawnRecord == null) { Messages.Message(modString, MessageTypeDefOf.SilentInput); Messages.Message("EdB.PC.Dialog.PawnPreset.Error.Failed".Translate(), MessageTypeDefOf.RejectInput); Log.Warning("Colonist was created with the following mods: " + modString); return(null); } PresetLoaderVersion4 loader = new PresetLoaderVersion4(); CustomPawn loadedPawn = loader.LoadPawn(pawnRecord); if (loadedPawn != null) { CustomPawn idConflictPawn = PrepareCarefully.Instance.Pawns.FirstOrDefault((CustomPawn p) => { return(p.Id == loadedPawn.Id); }); if (idConflictPawn != null) { loadedPawn.GenerateId(); } return(loadedPawn); } else { loadout.State.AddError(modString); loadout.State.AddError("EdB.PC.Dialog.Preset.Error.NoCharacter".Translate()); Log.Warning("Preset was created with the following mods: " + modString); return(null); } }
// // Static Methods // public static void SaveToFile(PrepareCarefully data, string presetName) { bool problem = false; try { // Verify that all pawns have non-null identifiers. foreach (CustomPawn customPawn in data.Pawns) { if (customPawn.Id == null) { customPawn.GenerateId(); } } foreach (var g in data.RelationshipManager.ParentChildGroups) { foreach (var parent in g.Parents) { if (parent != null && parent.Id == null) { parent.GenerateId(); } foreach (var child in g.Children) { if (child != null && child.Id == null) { child.GenerateId(); } } } } SaveRecordPresetV4 preset = new SaveRecordPresetV4(); preset.mods = GenText.ToCommaList(Enumerable.Select <ModContentPack, string>(LoadedModManager.RunningMods, (Func <ModContentPack, string>)(mod => mod.Name)), true); foreach (CustomPawn customPawn in data.Pawns) { SaveRecordPawnV4 pawn = new SaveRecordPawnV4(customPawn); preset.pawns.Add(pawn); } foreach (var g in data.RelationshipManager.ParentChildGroups) { foreach (var parent in g.Parents) { if (parent.Hidden) { if (parent.Pawn != null) { SaveRecordPawnV4 pawn = new SaveRecordPawnV4(parent); preset.pawns.Add(pawn); } else { Log.Warning("Prepare Carefully found an empty pawn in a parent child relationship while saving the preset. Skipping that pawn."); } } foreach (var child in g.Children) { if (child.Hidden) { if (child.Pawn != null) { SaveRecordPawnV4 pawn = new SaveRecordPawnV4(child); preset.pawns.Add(pawn); } else { Log.Warning("Prepare Carefully found an empty pawn in a parent child relationship while saving the preset. Skipping that pawn."); } } } } } foreach (var r in data.RelationshipManager.Relationships) { if (r.source != null && r.target != null && r.def != null && r.source.Id != null && r.target.Id != null) { SaveRecordRelationshipV3 s = new SaveRecordRelationshipV3(r); preset.relationships.Add(s); } else { problem = true; Log.Warning("Prepare Carefully found an invalid custom relationship when saving a preset: " + presetName); if (r.target != null && r.source != null) { Log.Warning(" Relationship = { source = " + r.source.Id + ", target = " + r.target.Id + ", relationship = " + r.def + "}"); } else { Log.Warning(" Relationship = { source = " + r.source + ", target = " + r.target + ", relationship = " + r.def + "}"); } } } foreach (var g in data.RelationshipManager.ParentChildGroups) { if (g.Children.Count == 0 || (g.Parents.Count == 0 && g.Children.Count == 1)) { continue; } SaveRecordParentChildGroupV3 group = new SaveRecordParentChildGroupV3(); group.parents = new List <string>(); group.children = new List <string>(); foreach (var p in g.Parents) { if (p.Pawn == null) { problem = true; Log.Warning("Prepare Carefully found an invalid parent/child relationship when saving the preset: " + presetName); continue; } else { group.parents.Add(p.Id); } } foreach (var p in g.Children) { if (p.Pawn == null) { problem = true; Log.Warning("Prepare Carefully found an invalid parent/child relationship when saving the preset: " + presetName); continue; } else { group.children.Add(p.Id); } } preset.parentChildGroups.Add(group); } foreach (var e in data.Equipment) { SaveRecordEquipmentV3 record = new SaveRecordEquipmentV3(e); preset.equipment.Add(record); } // Start saving. Scribe.saver.InitSaving(PresetFiles.FilePathForSavedPreset(presetName), "preset"); preset.ExposeData(); } catch (Exception e) { PrepareCarefully.Instance.State.AddError("EdB.PC.Dialog.Preset.Error.SaveFailed".Translate()); Log.Error("Failed to save preset file"); throw e; } finally { Scribe.saver.FinalizeSaving(); Scribe.mode = LoadSaveMode.Inactive; if (problem) { PrepareCarefully.Instance.State.AddError("EdB.PC.Dialog.Preset.Error.PartialSaveFailure".Translate()); } } }