public void AddChildToParentChildGroup(CustomParentChildGroup group, CustomParentChildPawn pawn) { if (!group.Parents.Contains(pawn) && !group.Children.Contains(pawn)) { group.Children.Add(pawn); } }
public void RemoveChildFromParentChildGroup(CustomParentChildGroup group, CustomParentChildPawn pawn) { group.Children.Remove(pawn); if (group.Parents.Count == 0 && group.Children.Count == 0) { PrepareCarefully.Instance.RelationshipManager.RemoveParentChildGroup(group); } }
protected void ShowChildDialogForGroup(CustomParentChildGroup group, CustomParentChildPawn selected, Action <CustomParentChildPawn> action) { CustomParentChildPawn selectedPawn = selected; HashSet <CustomParentChildPawn> disabled = new HashSet <CustomParentChildPawn>(); if (group != null) { disabled.AddRange(group.Parents); disabled.AddRange(group.Children); } rowGroups.Clear(); rowGroups.Add(new WidgetTable <CustomParentChildPawn> .RowGroup("EdB.PC.AddParentChild.Header.SelectColonist".Translate(), PrepareCarefully.Instance.RelationshipManager.ColonyPawns)); rowGroups.Add(new WidgetTable <CustomParentChildPawn> .RowGroup("EdB.PC.AddParentChild.Header.SelectHidden".Translate(), PrepareCarefully.Instance.RelationshipManager.HiddenPawns)); WidgetTable <CustomParentChildPawn> .RowGroup newPawnGroup = new WidgetTable <CustomParentChildPawn> .RowGroup(null, newPawns); rowGroups.Add(newPawnGroup); DialogSelectParentChildPawn pawnDialog = new DialogSelectParentChildPawn() { HeaderLabel = "EdB.PC.AddParentChild.Header.AddChild".Translate(), SelectAction = (CustomParentChildPawn pawn) => { selectedPawn = pawn; }, RowGroups = rowGroups, DisabledPawns = disabled, ConfirmValidation = () => { if (selectedPawn == null) { return("EdB.PC.AddParentChild.Error.ChildRequired"); } else { return(null); } }, CloseAction = () => { // If the user selected a new pawn, replace the pawn in the new pawn list with another one. int index = newPawnGroup.Rows.FirstIndexOf((CustomParentChildPawn p) => { return(p == selectedPawn); }); if (index > -1 && index < newPawns.Count) { selectedPawn = ReplaceNewHiddenCharacter(index); } action(selectedPawn); } }; Find.WindowStack.Add(pawnDialog); }
private void InitializeParentChildGroupRelationships(List <CustomRelationship> relationships) { Dictionary <CustomParentChildPawn, CustomParentChildGroup> groupLookup = new Dictionary <CustomParentChildPawn, CustomParentChildGroup>(); foreach (var relationship in relationships) { CustomParentChildPawn parent = null; CustomParentChildPawn child = null; if (relationship.def == PawnRelationDefOf.Parent) { parentChildCustomPawnLookup.TryGetValue(relationship.source, out child); parentChildCustomPawnLookup.TryGetValue(relationship.target, out parent); } else if (relationship.def == PawnRelationDefOf.Child) { parentChildCustomPawnLookup.TryGetValue(relationship.target, out child); parentChildCustomPawnLookup.TryGetValue(relationship.source, out parent); } if (parent == null) { Log.Warning("Could not add relationship because of missing parent"); continue; } if (child == null) { Log.Warning("Could not add relationship because of missing child"); continue; } // See if the child has an existing parent/child group. If not, create the group. // If so, just add the parent. CustomParentChildGroup group; if (!groupLookup.TryGetValue(child, out group)) { group = new CustomParentChildGroup(); group.Children.Add(child); groupLookup.Add(child, group); } group.Parents.Add(parent); } SortAndDedupeParentChildGroups(groupLookup.Values); }
private void InitializeParentChildGroupsForStartingPawns(List <Pawn> pawns, List <CustomPawn> correspondingFacades) { // Create a map so that we can look up custom pawns based on their matching original pawn. Dictionary <Pawn, CustomPawn> pawnToFacadeMap = new Dictionary <Pawn, CustomPawn>(); int pawnCount = pawns.Count; for (int i = 0; i < pawns.Count; i++) { pawnToFacadeMap.Add(pawns[i], correspondingFacades[i]); } // Go through each pawn and look for a child/parent relationship between it and all other pawns. Dictionary <Pawn, CustomParentChildGroup> groupLookup = new Dictionary <Pawn, CustomParentChildGroup>(); foreach (Pawn child in pawns) { foreach (var r in child.relations.DirectRelations) { //Log.Message("Relationship: " + r.def.defName + ", " + child.LabelShort + " & " + r.otherPawn.LabelShort); if (r.def == PawnRelationDefOf.Parent) { Pawn parent = r.otherPawn; CustomParentChildPawn parentCustomPawn = parentChildPawnLookup[parent]; CustomParentChildPawn childCustomPawn = parentChildPawnLookup[child]; // See if the child has an existing parent/child group. If not, create the group. // If so, just add the parent. CustomParentChildGroup group; if (!groupLookup.TryGetValue(child, out group)) { group = new CustomParentChildGroup(); group.Children.Add(childCustomPawn); groupLookup.Add(child, group); } group.Parents.Add(parentCustomPawn); } } } SortAndDedupeParentChildGroups(groupLookup.Values); }
public void AddParentChildGroup(CustomParentChildGroup group) { PrepareCarefully.Instance.RelationshipManager.ParentChildGroups.Add(group); }
protected float DrawNextGroup(float cursor) { int parentBoxCount = 1; int childBoxCount = 1; float widthOfParents = parentBoxCount * SizePawn.x + (SpacingPawn * (parentBoxCount - 1)) + (PaddingBox * 2); float widthOfChildren = SizeChildOffset + (childBoxCount * SizePawn.x) + (SpacingPawn * (childBoxCount - 1)) + (PaddingBox * 2); float width = Mathf.Max(widthOfChildren, widthOfParents); float height = PaddingBox * 2 + SpacingArrow * 2 + SizeArrowBase.y + SizeArrowHead.y + SizePawn.y * 2; Rect rect = new Rect(cursor, 0, width, height); GUI.color = Style.ColorPanelBackgroundItem; GUI.DrawTexture(rect, BaseContent.WhiteTex); GUI.BeginGroup(rect); try { Rect parentPawnRect = new Rect(PaddingBox, PaddingBox, SizePawn.x, SizePawn.y); GUI.color = ColorParentEmpty; GUI.DrawTexture(parentPawnRect, BaseContent.WhiteTex); Rect addParentRect = new Rect(parentPawnRect.xMax - PaddingAddButton - SizeAddButton.x, parentPawnRect.y + PaddingAddButton, SizeAddButton.x, SizeAddButton.y); Style.SetGUIColorForButton(parentPawnRect); GUI.DrawTexture(addParentRect, Textures.TextureButtonAdd); if (Widgets.ButtonInvisible(parentPawnRect)) { ShowParentDialogForGroup(null, null, (CustomParentChildPawn pawn) => { CustomParentChildGroup group = new CustomParentChildGroup(); group.Parents.Add(pawn); GroupAdded(group); }); } GUI.color = ColorParentEmpty; Rect arrowBaseRect = new Rect(parentPawnRect.MiddleX() - SizeArrowBase.HalfX(), parentPawnRect.yMax, SizeArrowBase.x, SpacingArrow); GUI.DrawTexture(arrowBaseRect, BaseContent.WhiteTex); GUI.color = ColorChildEmpty; Rect childPawnRect = new Rect(PaddingBox + SizeChildOffset, PaddingBox + SizePawn.y + SizeArrowBase.y + SizeArrowHead.y + SpacingArrow * 2, SizePawn.x, SizePawn.y); float arrowBaseLeft = parentPawnRect.MiddleX() - SizeArrowBase.HalfX(); GUI.DrawTexture(childPawnRect, BaseContent.WhiteTex); Rect addChildRect = new Rect(childPawnRect.xMax - PaddingAddButton - SizeAddButton.x, childPawnRect.y + PaddingAddButton, SizeAddButton.x, SizeAddButton.y); Style.SetGUIColorForButton(childPawnRect); GUI.DrawTexture(addChildRect, Textures.TextureButtonAdd); if (Widgets.ButtonInvisible(childPawnRect)) { ShowChildDialogForGroup(null, null, (CustomParentChildPawn pawn) => { CustomParentChildGroup group = new CustomParentChildGroup(); group.Children.Add(pawn); GroupAdded(group); }); } GUI.color = ColorParentEmpty; arrowBaseRect = new Rect(childPawnRect.MiddleX() - SizeArrowBase.HalfX(), childPawnRect.y - SizeArrowHead.y - SpacingArrow, SizeArrowBase.x, SpacingArrow); GUI.DrawTexture(arrowBaseRect, BaseContent.WhiteTex); float arrowBaseRightChild = arrowBaseRect.xMax; Rect arrowHeadRect = new Rect(childPawnRect.MiddleX() - SizeArrowHead.HalfX(), childPawnRect.y - SizeArrowHead.y, SizeArrowHead.x, SizeArrowHead.y); GUI.DrawTexture(arrowHeadRect, Textures.TextureArrowDown); Rect arrowBaseLineRect = new Rect(arrowBaseLeft, PaddingBox + SizePawn.y + SpacingArrow, arrowBaseRightChild - arrowBaseLeft, SizeArrowBase.y); GUI.DrawTexture(arrowBaseLineRect, BaseContent.WhiteTex); } finally { GUI.EndGroup(); } GUI.color = Color.white; cursor += width + SpacingGroup; return(cursor); }
protected float DrawGroup(float cursor, CustomParentChildGroup group) { int parentBoxCount = group.Parents.Count + 1; int childBoxCount = group.Children.Count + 1; float widthOfParents = parentBoxCount * SizePawn.x + (SpacingPawn * (parentBoxCount - 1)) + (PaddingBox * 2); float widthOfChildren = SizeChildOffset + (childBoxCount * SizePawn.x) + (SpacingPawn * (childBoxCount - 1)) + (PaddingBox * 2); float width = Mathf.Max(widthOfChildren, widthOfParents); float height = PaddingBox * 2 + SpacingArrow * 2 + SizeArrowBase.y + SizeArrowHead.y + SizePawn.y * 2; Rect rect = new Rect(cursor, 0, width, height); GUI.color = Style.ColorPanelBackgroundItem; GUI.DrawTexture(rect, BaseContent.WhiteTex); GUI.BeginGroup(rect); try { Color arrowColor = group.Parents.Count > 0 ? ColorParent : ColorParentEmpty; Rect firstParentPawnRect = new Rect(PaddingBox, PaddingBox, SizePawn.x, SizePawn.y); Rect parentPawnRect = firstParentPawnRect; float arrowBaseRightParent = 0; foreach (var parent in group.Parents) { GUI.color = ColorParent; GUI.DrawTexture(parentPawnRect, BaseContent.WhiteTex); Rect arrowBaseRect = new Rect(parentPawnRect.MiddleX() - SizeArrowBase.HalfX(), parentPawnRect.yMax, SizeArrowBase.x, SpacingArrow); arrowBaseRightParent = arrowBaseRect.xMax; GUI.DrawTexture(arrowBaseRect, BaseContent.WhiteTex); DrawPortrait(parent, parentPawnRect); if (parentPawnRect.Contains(Event.current.mousePosition)) { Rect deleteRect = new Rect(parentPawnRect.xMax - PaddingDeleteButton - SizeDeleteButton.x, parentPawnRect.y + PaddingDeleteButton, SizeDeleteButton.x, SizeDeleteButton.y); Style.SetGUIColorForButton(deleteRect); GUI.DrawTexture(deleteRect, Textures.TextureButtonDelete); if (Widgets.ButtonInvisible(deleteRect)) { parentsToRemove.Add(new PawnGroupPair(parent, group)); } } parentPawnRect.x += SizePawn.x + SpacingPawn; } // If there's no parent, we still want to draw the arrow that points from the first parent box to the first child. // Normally, we would have drawn it when we drew the parent, but since there's aren't any parents, we have to call // it out here and draw it separately. if (group.Parents.Count == 0) { GUI.color = arrowColor; Rect arrowBaseRect = new Rect(parentPawnRect.MiddleX() - SizeArrowBase.HalfX(), parentPawnRect.yMax, SizeArrowBase.x, SpacingArrow); GUI.DrawTexture(arrowBaseRect, BaseContent.WhiteTex); arrowBaseRightParent = arrowBaseRect.x; } GUI.color = ColorParentEmpty; GUI.DrawTexture(parentPawnRect, BaseContent.WhiteTex); Rect addParentRect = new Rect(parentPawnRect.xMax - PaddingAddButton - SizeAddButton.x, parentPawnRect.y + PaddingAddButton, SizeAddButton.x, SizeAddButton.y); Style.SetGUIColorForButton(parentPawnRect); GUI.DrawTexture(addParentRect, Textures.TextureButtonAdd); if (Widgets.ButtonInvisible(parentPawnRect)) { ShowParentDialogForGroup(group, null, (CustomParentChildPawn pawn) => { ParentAddedToGroup(group, pawn); }); } Rect childPawnRect = new Rect(PaddingBox + SizeChildOffset, PaddingBox + SizePawn.y + SizeArrowBase.y + SizeArrowHead.y + SpacingArrow * 2, SizePawn.x, SizePawn.y); float arrowBaseLeft = firstParentPawnRect.MiddleX() - SizeArrowBase.HalfX(); float arrowBaseRightChild = arrowBaseLeft + SizeArrowBase.x; foreach (var child in group.Children) { GUI.color = ColorChild; GUI.DrawTexture(childPawnRect, BaseContent.WhiteTex); GUI.color = arrowColor; Rect arrowBaseRect = new Rect(childPawnRect.MiddleX() - SizeArrowBase.HalfX(), childPawnRect.y - SizeArrowHead.y - SpacingArrow, SizeArrowBase.x, SpacingArrow); GUI.DrawTexture(arrowBaseRect, BaseContent.WhiteTex); Rect arrowHeadRect = new Rect(childPawnRect.MiddleX() - SizeArrowHead.HalfX(), childPawnRect.y - SizeArrowHead.y, SizeArrowHead.x, SizeArrowHead.y); GUI.DrawTexture(arrowHeadRect, Textures.TextureArrowDown); DrawPortrait(child, childPawnRect); if (childPawnRect.Contains(Event.current.mousePosition)) { Rect deleteRect = new Rect(childPawnRect.xMax - PaddingDeleteButton - SizeDeleteButton.x, childPawnRect.y + PaddingDeleteButton, SizeDeleteButton.x, SizeDeleteButton.y); Style.SetGUIColorForButton(deleteRect); GUI.DrawTexture(deleteRect, Textures.TextureButtonDelete); if (Widgets.ButtonInvisible(deleteRect)) { childrenToRemove.Add(new PawnGroupPair(child, group)); } } childPawnRect.x += SizePawn.x + SpacingPawn; arrowBaseRightChild = arrowBaseRect.xMax; } // If there's no children, we still want to draw the arrow that points to the first child. // Normally, we would have drawn it when we drew the children, but since there's aren't any children, // we have to call it out here and draw it separately. if (group.Children.Count == 0) { GUI.color = arrowColor; Rect arrowBaseRect = new Rect(childPawnRect.MiddleX() - SizeArrowBase.HalfX(), childPawnRect.y - SizeArrowHead.y - SpacingArrow, SizeArrowBase.x, SpacingArrow); GUI.DrawTexture(arrowBaseRect, BaseContent.WhiteTex); Rect arrowHeadRect = new Rect(childPawnRect.MiddleX() - SizeArrowHead.HalfX(), childPawnRect.y - SizeArrowHead.y, SizeArrowHead.x, SizeArrowHead.y); GUI.DrawTexture(arrowHeadRect, Textures.TextureArrowDown); arrowBaseRightChild = arrowBaseRect.xMax; } GUI.color = ColorChildEmpty; GUI.DrawTexture(childPawnRect, BaseContent.WhiteTex); Rect addChildRect = new Rect(childPawnRect.xMax - PaddingAddButton - SizeAddButton.x, childPawnRect.y + PaddingAddButton, SizeAddButton.x, SizeAddButton.y); Style.SetGUIColorForButton(childPawnRect); GUI.DrawTexture(addChildRect, Textures.TextureButtonAdd); if (Widgets.ButtonInvisible(childPawnRect)) { ShowChildDialogForGroup(group, null, (CustomParentChildPawn pawn) => { ChildAddedToGroup(group, pawn); }); } float arrowBaseRight = Mathf.Max(arrowBaseRightChild, arrowBaseRightParent); Rect arrowBaseLineRect = new Rect(arrowBaseLeft, PaddingBox + SizePawn.y + SpacingArrow, arrowBaseRight - arrowBaseLeft, SizeArrowBase.y); GUI.color = arrowColor; GUI.DrawTexture(arrowBaseLineRect, BaseContent.WhiteTex); } finally { GUI.EndGroup(); } GUI.color = Color.white; cursor += width + SpacingGroup; return(cursor); }
public PawnGroupPair(CustomParentChildPawn Pawn, CustomParentChildGroup Group) { this.Pawn = Pawn; this.Group = Group; }
public void RemoveParentChildGroup(CustomParentChildGroup group) { parentChildGroups.Remove(group); }
public bool Load(PrepareCarefully loadout, string presetName) { List <SaveRecordPawnV3> pawns = new List <SaveRecordPawnV3>(); List <SaveRecordPawnV3> hiddenPawns = new List <SaveRecordPawnV3>(); List <SaveRecordRelationshipV3> savedRelationships = new List <SaveRecordRelationshipV3>(); List <SaveRecordParentChildGroupV3> parentChildGroups = new List <SaveRecordParentChildGroupV3>(); Failed = false; int startingPoints = 0; bool usePoints = false; try { Scribe.loader.InitLoading(PresetFiles.FilePathForSavedPreset(presetName)); Scribe_Values.Look <bool>(ref usePoints, "usePoints", true, false); Scribe_Values.Look <int>(ref startingPoints, "startingPoints", 0, false); Scribe_Values.Look <string>(ref ModString, "mods", "", false); try { Scribe_Collections.Look <SaveRecordPawnV3>(ref pawns, "colonists", LookMode.Deep, null); } catch (Exception e) { Messages.Message("EdB.PC.Dialog.Preset.Error.Failed".Translate(), MessageTypeDefOf.ThreatBig); Log.Warning(e.ToString()); Log.Warning("Preset was created with the following mods: " + ModString); return(false); } try { Scribe_Collections.Look <SaveRecordPawnV3>(ref hiddenPawns, "hiddenPawns", LookMode.Deep, null); } catch (Exception e) { Messages.Message("EdB.PC.Dialog.Preset.Error.Failed".Translate(), MessageTypeDefOf.ThreatBig); Log.Warning(e.ToString()); Log.Warning("Preset was created with the following mods: " + ModString); return(false); } try { Scribe_Collections.Look <SaveRecordRelationshipV3>(ref savedRelationships, "relationships", LookMode.Deep, null); } catch (Exception e) { Messages.Message("EdB.PC.Dialog.Preset.Error.Failed".Translate(), MessageTypeDefOf.ThreatBig); Log.Warning(e.ToString()); Log.Warning("Preset was created with the following mods: " + ModString); return(false); } try { Scribe_Collections.Look <SaveRecordParentChildGroupV3>(ref parentChildGroups, "parentChildGroups", LookMode.Deep, null); } catch (Exception e) { Messages.Message("EdB.PC.Dialog.Preset.Error.Failed".Translate(), MessageTypeDefOf.ThreatBig); Log.Warning(e.ToString()); Log.Warning("Preset was created with the following mods: " + ModString); return(false); } List <EquipmentSaveRecord> tempEquipment = new List <EquipmentSaveRecord>(); Scribe_Collections.Look <EquipmentSaveRecord>(ref tempEquipment, "equipment", LookMode.Deep, null); loadout.Equipment.Clear(); if (tempEquipment != null) { List <EquipmentSelection> equipment = new List <EquipmentSelection>(tempEquipment.Count); foreach (var e in tempEquipment) { ThingDef thingDef = DefDatabase <ThingDef> .GetNamedSilentFail(e.def); if (thingDef == null) { string replacementDefName; if (thingDefReplacements.TryGetValue(e.def, out replacementDefName)) { thingDef = DefDatabase <ThingDef> .GetNamedSilentFail(replacementDefName); } } ThingDef stuffDef = null; Gender gender = Gender.None; if (!string.IsNullOrEmpty(e.stuffDef)) { stuffDef = DefDatabase <ThingDef> .GetNamedSilentFail(e.stuffDef); } if (!string.IsNullOrEmpty(e.gender)) { try { gender = (Gender)Enum.Parse(typeof(Gender), e.gender); } catch (Exception) { Log.Warning("Failed to load gender value for animal."); Failed = true; continue; } } if (thingDef != null) { if (string.IsNullOrEmpty(e.stuffDef)) { EquipmentKey key = new EquipmentKey(thingDef, null, gender); EquipmentRecord record = PrepareCarefully.Instance.EquipmentDatabase[key]; if (record != null) { equipment.Add(new EquipmentSelection(record, e.count)); } else { Log.Warning("Could not find equipment in equipment database: " + key); Failed = true; continue; } } else { if (stuffDef != null) { EquipmentKey key = new EquipmentKey(thingDef, stuffDef, gender); EquipmentRecord record = PrepareCarefully.Instance.EquipmentDatabase[key]; if (record == null) { string thing = thingDef != null ? thingDef.defName : "null"; string stuff = stuffDef != null ? stuffDef.defName : "null"; Log.Warning(string.Format("Could not load equipment/resource from the preset. This may be caused by an invalid thing/stuff combination: " + key)); Failed = true; continue; } else { equipment.Add(new EquipmentSelection(record, e.count)); } } else { Log.Warning("Could not load stuff definition \"" + e.stuffDef + "\" for item \"" + e.def + "\""); Failed = true; } } } else { Log.Warning("Could not load thing definition \"" + e.def + "\""); Failed = true; } } loadout.Equipment.Clear(); foreach (var e in equipment) { loadout.Equipment.Add(e); } } else { Messages.Message("EdB.PC.Dialog.Preset.Error.EquipmentFailed".Translate(), MessageTypeDefOf.ThreatBig); Log.Warning("Failed to load equipment from preset"); Failed = true; } //PrepareCarefully.Instance.Config.pointsEnabled = usePoints; } 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)); if (saveables != null) { saveables.Clear(); } List <IExposable> crossReferencingExposables = (List <IExposable>)(typeof(CrossRefHandler).GetField("crossReferencingExposables", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(Scribe.loader.crossRefs)); if (crossReferencingExposables != null) { crossReferencingExposables.Clear(); } Scribe.loader.FinalizeLoading(); } List <CustomPawn> allPawns = new List <CustomPawn>(); List <CustomPawn> colonistCustomPawns = new List <CustomPawn>(); try { foreach (SaveRecordPawnV3 p in pawns) { CustomPawn pawn = LoadPawn(p); if (pawn != null) { allPawns.Add(pawn); colonistCustomPawns.Add(pawn); } else { Messages.Message("EdB.PC.Dialog.Preset.Error.NoCharacter".Translate(), MessageTypeDefOf.ThreatBig); Log.Warning("Preset was created with the following mods: " + ModString); } } } catch (Exception e) { Messages.Message("EdB.PC.Dialog.Preset.Error.Failed".Translate(), MessageTypeDefOf.ThreatBig); Log.Warning(e.ToString()); Log.Warning("Preset was created with the following mods: " + ModString); return(false); } List <CustomPawn> hiddenCustomPawns = new List <CustomPawn>(); try { if (hiddenPawns != null) { foreach (SaveRecordPawnV3 p in hiddenPawns) { CustomPawn pawn = LoadPawn(p); if (pawn != null) { allPawns.Add(pawn); hiddenCustomPawns.Add(pawn); } else { Log.Warning("Prepare Carefully failed to load a hidden character from the preset"); } } } } catch (Exception e) { Messages.Message("EdB.PC.Dialog.Preset.Error.Failed".Translate(), MessageTypeDefOf.ThreatBig); Log.Warning(e.ToString()); Log.Warning("Preset was created with the following mods: " + ModString); return(false); } loadout.ClearPawns(); foreach (CustomPawn p in colonistCustomPawns) { loadout.AddPawn(p); } loadout.RelationshipManager.Clear(); loadout.RelationshipManager.InitializeWithParentChildPawns(colonistCustomPawns, hiddenCustomPawns); bool atLeastOneRelationshipFailed = false; List <CustomRelationship> allRelationships = new List <CustomRelationship>(); if (savedRelationships != null) { try { foreach (SaveRecordRelationshipV3 r in savedRelationships) { if (string.IsNullOrEmpty(r.source) || string.IsNullOrEmpty(r.target) || string.IsNullOrEmpty(r.relation)) { atLeastOneRelationshipFailed = true; Log.Warning("Prepare Carefully failed to load a custom relationship from the preset: " + r); continue; } CustomRelationship relationship = LoadRelationship(r, allPawns); if (relationship == null) { atLeastOneRelationshipFailed = true; Log.Warning("Prepare Carefully failed to load a custom relationship from the preset: " + r); } else { allRelationships.Add(relationship); } } } catch (Exception e) { Messages.Message("EdB.PC.Dialog.Preset.Error.RelationshipFailed".Translate(), MessageTypeDefOf.ThreatBig); Log.Warning(e.ToString()); Log.Warning("Preset was created with the following mods: " + ModString); return(false); } if (atLeastOneRelationshipFailed) { Messages.Message("EdB.PC.Dialog.Preset.Error.RelationshipFailed".Translate(), MessageTypeDefOf.ThreatBig); } } loadout.RelationshipManager.AddRelationships(allRelationships); if (parentChildGroups != null) { foreach (var groupRecord in parentChildGroups) { CustomParentChildGroup group = new CustomParentChildGroup(); if (groupRecord.parents != null) { foreach (var id in groupRecord.parents) { CustomPawn parent = FindPawnById(id, colonistCustomPawns, hiddenCustomPawns); if (parent != null) { var pawn = loadout.RelationshipManager.FindParentChildPawn(parent); if (pawn != null) { group.Parents.Add(pawn); } else { Log.Warning("Prepare Carefully could not load a custom parent relationship because it could not find a matching pawn in the relationship manager."); } } else { Log.Warning("Prepare Carefully could not load a custom parent relationship because it could not find a pawn with the saved identifer."); } } } if (groupRecord.children != null) { foreach (var id in groupRecord.children) { CustomPawn child = FindPawnById(id, colonistCustomPawns, hiddenCustomPawns); if (child != null) { var pawn = loadout.RelationshipManager.FindParentChildPawn(child); if (pawn != null) { group.Children.Add(pawn); } else { Log.Warning("Prepare Carefully could not load a custom child relationship because it could not find a matching pawn in the relationship manager."); } } else { Log.Warning("Prepare Carefully could not load a custom child relationship because it could not find a pawn with the saved identifer."); } } } loadout.RelationshipManager.ParentChildGroups.Add(group); } } loadout.RelationshipManager.ReassignHiddenPawnIndices(); if (Failed) { Messages.Message(ModString, MessageTypeDefOf.SilentInput); Messages.Message("EdB.PC.Dialog.Preset.Error.ThingDefFailed".Translate(), MessageTypeDefOf.ThreatBig); Log.Warning("Preset was created with the following mods: " + ModString); return(false); } return(true); }