예제 #1
0
        private void AddToFamily(FAMI family, Neighbour neigh, VM vm)
        {
            //was the neighbor already in a family?
            if (neigh.PersonData != null)
            {
                var famID  = neigh.PersonData[(int)VMPersonDataVariable.TS1FamilyNumber];
                var oldFam = Content.Content.Get().Neighborhood.GetFamily((ushort)famID);
                if (oldFam != null && oldFam.ChunkID != 0)
                {
                    var oguids = oldFam.FamilyGUIDs.ToList();
                    oguids.Remove(neigh.GUID);
                    oldFam.FamilyGUIDs = oguids.ToArray();
                    TryDeleteFamily(oldFam);
                }
                neigh.PersonData[(int)VMPersonDataVariable.TS1FamilyNumber] = (short)family.ChunkID;
            }

            var guids = family.FamilyGUIDs.ToList();

            guids.Add(neigh.GUID);
            family.FamilyGUIDs = guids.ToArray();

            //if the sim is on the lot, change their runtime person data to reflect the new family id.
            var runtime = (VMAvatar)vm.Context.ObjectQueries.Avatars.FirstOrDefault(x => ((VMAvatar)x).GetPersonData(VMPersonDataVariable.NeighborId) == neigh.NeighbourID);

            runtime?.SetPersonData(VMPersonDataVariable.TS1FamilyNumber, (short)family.ChunkID);
        }
예제 #2
0
        public UIFamilyCASItem(UIFamiliesCASPanel parent, FAMI family, VM vm)
        {
            FParent = parent;
            var ui = Content.Get().CustomUI;
            var gd = GameFacade.GraphicsDevice;

            PxWhite    = TextureGenerator.GetPxWhite(gd);
            Grad       = ui.Get("dialog_title_grad.png").Get(gd);
            Background = new UIImage(ui.Get("circle10px.png").Get(gd)).With9Slice(19, 19, 19, 19);
            //set the width based on number of family members
            //30 margin on family thumbs
            Width = 100 * family.FamilyGUIDs.Length + 10;
            Background.SetSize(Width, 120);
            Background.Position = new Vector2((MaxWidth - Width) / 2, 40);
            Add(Background);

            //max width is 100*8+10, 810

            var fams = family.ChunkParent.Get <FAMs>(family.ChunkID);

            FamilyTitle = new UILabel();
            FamilyTitle.CaptionStyle       = FamilyTitle.CaptionStyle.Clone();
            FamilyTitle.CaptionStyle.Color = UIStyle.Current.Text;
            FamilyTitle.CaptionStyle.Size  = 19;
            FamilyTitle.Size      = new Vector2(MaxWidth, 40);
            FamilyTitle.Alignment = TextAlignment.Center | TextAlignment.Middle;
            FamilyTitle.Caption   = fams?.GetString(0) ?? "";
            Add(FamilyTitle);

            TitleWidth = (int)FamilyTitle.CaptionStyle.MeasureString(FamilyTitle.Caption).X + 30;

            //display heads of all family members
            InitAvatarList(family.FamilyGUIDs, vm);
            SelectPct = SelectPct;
        }
예제 #3
0
 public void EvictLot(FAMI family, short houseID)
 {
     family.Budget     += family.ValueInArch;
     family.ValueInArch = 0;
     Content.Get().Neighborhood.MoveOut(houseID);
     TS1NeighPanel.SelectHouse(houseID);
 }
        public void PopulateList(FAMI family)
        {
            var world = new FSO.LotView.World(GameFacade.GraphicsDevice);

            world.Initialize(GameFacade.Scenes);
            var context = new VMContext(world);
            var vm      = new VM(context, new VMServerDriver(new VMTS1GlobalLinkStub()), new VMNullHeadlineProvider());

            vm.Init();
            var blueprint = new Blueprint(1, 1);

            //world.InitBlueprint(blueprint);
            context.Blueprint    = blueprint;
            context.Architecture = new VMArchitecture(1, 1, blueprint, vm.Context);

            int i     = 0;
            var baseX = 0;

            foreach (var sim in family.FamilyGUIDs)
            {
                var fam = vm.Context.CreateObjectInstance(sim, LotTilePos.OUT_OF_WORLD, Direction.NORTH, true).BaseObject;
                var btn = new UIAvatarSelectButton(UIIconCache.GetObject(fam));
                btn.Opacity = 1f;
                var id = i;
                btn.Name = fam.Name;
                btn.X    = baseX + (i++) * 100;
                btn.Y    = 0;
                btn.DeregisterHandler();
                Btns.Add(btn);
                Add(btn);
                fam.Delete(true, vm.Context);
            }
            world.Dispose();
        }
예제 #5
0
        public FAMI GetFamilyForHouse(short ID)
        {
            FAMI result = null;

            FamilyForHouse.TryGetValue(ID, out result);
            return(result);
        }
예제 #6
0
        public SandboxGameScreen() : base()
        {
            StateChanges = new Queue <SimConnectStateChange>();

            ucp   = new UIUCP(this);
            ucp.Y = ScreenHeight - 210;
            ucp.SetInLot(false);
            ucp.UpdateZoomButton();
            ucp.MoneyText.Caption = "0";// PlayerAccount.Money.ToString();
            this.Add(ucp);

            Title = new UIGameTitle();
            Title.SetTitle("");
            this.Add(Title);

            WindowContainer = new UIContainer();
            Add(WindowContainer);

            if (Content.Content.Get().TS1)
            {
                TS1NeighPanel = new UINeighborhoodSelectionPanel(4);
                TS1NeighPanel.OnHouseSelect += (house) =>
                {
                    ActiveFamily = Content.Content.Get().Neighborhood.GetFamilyForHouse((short)house);
                    InitializeLot(Path.Combine(Content.Content.Get().TS1BasePath, "UserData/Houses/House" + house.ToString().PadLeft(2, '0') + ".iff"), false);// "UserData/Houses/House21.iff"
                    Remove(TS1NeighPanel);
                };
                Add(TS1NeighPanel);
            }
        }
예제 #7
0
 private void TryDeleteFamily(FAMI family)
 {
     //delete the family if there's no people in it
     if (family.FamilyGUIDs.Length == 0)
     {
         family.ChunkParent.FullRemoveChunk(family);
     }
 }
예제 #8
0
 public int GetMagicoinsForFamily(FAMI family)
 {
     if (family == null)
     {
         return(0);
     }
     return(family.FamilyGUIDs.Select(x => GetMagicoinsForNeighbor(GetNeighborIDForGUID(x) ?? -1)).Sum());
 }
예제 #9
0
 public void SetFamilyForHouse(short houseID, FAMI family, bool buy)
 {
     family.HouseNumber = houseID;
     if (buy)
     {
         family.Budget -= GetHouse(houseID)?.Get <SIMI>(1)?.PurchaseValue ?? 0;
     }
     FamilyForHouse[houseID] = family;
 }
예제 #10
0
 public void ActivateFamily(VM vm, FAMI family)
 {
     if (family == null)
     {
         return;
     }
     vm.SetGlobalValue(9, (short)family.ChunkID);
     CurrentFamily = family;
 }
예제 #11
0
 public void PlayHouse(short house, UIElement switcher)
 {
     ActiveFamily = Content.Get().Neighborhood.GetFamilyForHouse((short)house);
     InitializeLot(Content.Get().Neighborhood.GetHousePath(house), false);// "UserData/Houses/House21.iff"
     Remove(TS1NeighPanel);
     if (switcher != null)
     {
         Remove(switcher);
     }
 }
예제 #12
0
        public void NeighSelection()
        {
            TS1NeighPanel = new UINeighborhoodSelectionPanel(4);
            var switcher = new UINeighbourhoodSwitcher(TS1NeighPanel, 4);

            TS1NeighPanel.OnHouseSelect += (house) =>
            {
                ActiveFamily = Content.Get().Neighborhood.GetFamilyForHouse((short)house);
                InitializeLot(Path.Combine(FSOEnvironment.UserDir, "UserData/Houses/House" + house.ToString().PadLeft(2, '0') + ".iff"), false);// "UserData/Houses/House21.iff"
                Remove(TS1NeighPanel);
                Remove(switcher);
            };
            Add(TS1NeighPanel);
            Add(switcher);
        }
예제 #13
0
        public TS1GameScreen() : base()
        {
            Bg          = new UISimitoneBg();
            Bg.Position = (new Vector2(ScreenWidth, ScreenHeight)) / 2;
            Add(Bg);

            WindowContainer = new UIContainer();
            Add(WindowContainer);

            if (Content.Get().TS1)
            {
                TS1NeighPanel = new UINeighborhoodSelectionPanel(4);
                TS1NeighPanel.OnHouseSelect += (house) =>
                {
                    ActiveFamily = Content.Get().Neighborhood.GetFamilyForHouse((short)house);
                    InitializeLot(Path.Combine(Content.Get().TS1BasePath, "UserData/Houses/House" + house.ToString().PadLeft(2, '0') + ".iff"), false);// "UserData/Houses/House21.iff"
                    Remove(TS1NeighPanel);
                };
                Add(TS1NeighPanel);
            }
        }
예제 #14
0
        public override void Deserialize(BinaryReader reader)
        {
            if (reader.ReadBoolean())
            {
                SimulationInfo = new SIMI()
                {
                    ChunkID = 1, ChunkLabel = "", ChunkType = "SIMI"
                };
                SimulationInfo.Read(null, reader.BaseStream);
            }

            //this is really only here for future networking. families should be activated (see abover) when joining lots for the first time
            var famID = reader.ReadUInt16();

            if (famID < 65535)
            {
                CurrentFamily = new FAMI()
                {
                    ChunkID = famID, ChunkLabel = "", ChunkType = "FAMI"
                };
                CurrentFamily.Read(null, reader.BaseStream);
            }
        }
        public void Evict(FAMI family)
        {
            if (family == null)
            {
                return;
            }
            var           familyName  = family.ChunkParent.Get <FAMs>(family.ChunkID)?.GetString(0) ?? "selected";
            UIMobileAlert evictDialog = null;

            evictDialog = new UIMobileAlert(new UIAlertOptions()
            {
                Title   = GameFacade.Strings.GetString("131", "2"),
                Message = GameFacade.Strings.GetString("131", "3", new string[] {
                    familyName.ToString(),
                    "§" + (family.ValueInArch + family.Budget).ToString("##,#0")
                }
                                                       ),
                Buttons = UIAlertButton.YesNo(
                    (b) => { evictDialog.Close(); ((TS1GameScreen)UIScreen.Current).EvictLot(family, (short)HouseID); },
                    (b) => { evictDialog.Close(); }
                    )
            });
            UIScreen.GlobalShowDialog(evictDialog, true);
        }
 public UIHouseFamilyList(FAMI family)
 {
     PopulateList(family);
 }
예제 #17
0
        /// <summary>
        /// Get a variable
        /// </summary>
        /// <param name="context"></param>
        /// <param name="scope"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static short GetVariable(VMStackFrame context, VMVariableScope scope, short data)
        {
            switch (scope)
            {
            case VMVariableScope.MyObjectAttributes:     //0
                return(context.Caller.GetAttribute((ushort)data));

            case VMVariableScope.StackObjectAttributes:     //1
                return(context.StackObject.GetAttribute((ushort)data));

            case VMVariableScope.TargetObjectAttributes:     //2
                throw new VMSimanticsException("Target Object is Deprecated!", context);

            case VMVariableScope.MyObject:     //3
                return(context.Caller.GetValue((VMStackObjectVariable)data));

            case VMVariableScope.StackObject:     //4
                return(context.StackObject.GetValue((VMStackObjectVariable)data));

            case VMVariableScope.TargetObject:     //5
                throw new VMSimanticsException("Target Object is Deprecated!", context);

            case VMVariableScope.Global:     //6
                return(context.VM.GetGlobalValue((ushort)data));

            case VMVariableScope.Literal:     //7
                return(data);

            case VMVariableScope.Temps:     //8
                return(context.Thread.TempRegisters[data]);

            case VMVariableScope.Parameters:     //9
                return(context.Args[data]);

            case VMVariableScope.StackObjectID:     //10
                return(context.StackObjectID);

            case VMVariableScope.TempByTemp:     //11
                return(context.Thread.TempRegisters[context.Thread.TempRegisters[data]]);

            case VMVariableScope.TreeAdRange:     //12
                return(0);

            //throw new VMSimanticsException("Not implemented...", context);

            case VMVariableScope.StackObjectTemp:     //13
                return(context.StackObject.Thread.TempRegisters[data]);

            case VMVariableScope.MyMotives:     //14
                return(((VMAvatar)context.Caller).GetMotiveData((VMMotive)data));

            case VMVariableScope.StackObjectMotives:     //15
                return((context.StackObject as VMAvatar)?.GetMotiveData((VMMotive)data) ?? 0);

            case VMVariableScope.StackObjectSlot:     //16
                return(context.StackObject.GetSlot(data)?.ObjectID ?? 0);

            case VMVariableScope.StackObjectMotiveByTemp:     //17
                return(((VMAvatar)context.StackObject).GetMotiveData((VMMotive)context.Thread.TempRegisters[data]));

            case VMVariableScope.MyPersonData:     //18
                return(((VMAvatar)context.Caller).GetPersonData((VMPersonDataVariable)data));

            case VMVariableScope.StackObjectPersonData:     //19
                return(((VMAvatar)context.StackObject).GetPersonData((VMPersonDataVariable)data));

            case VMVariableScope.MySlot:     //20
                return(context.Caller.GetSlot(data)?.ObjectID ?? 0);

            case VMVariableScope.StackObjectDefinition:     //21
                return(GetEntityDefinitionVar(context.StackObject.Object.OBJ, (VMOBJDVariable)data, context));

            case VMVariableScope.StackObjectAttributeByParameter:     //22
                return(context.StackObject.GetAttribute((ushort)context.Args[data]));

            case VMVariableScope.RoomByTemp0:     //23
                //returns information on the selected room. Right now we don't have a room system, so always return the same values. (everywhere is indoors, not a pool)
                var roomID   = Math.Max(0, Math.Min(context.VM.Context.RoomInfo.Length - 1, context.Thread.TempRegisters[0]));
                var room     = context.VM.Context.RoomInfo[roomID];
                var baseroom = context.VM.Context.RoomInfo[room.Room.LightBaseRoom];

                if (data == 0)
                {
                    return(100);               //ambient light 0-100
                }
                else if (data == 1)
                {
                    return((short)((baseroom.Room.IsOutside)?1:0));                    //outside
                }
                else if (data == 2)
                {
                    return((short)(baseroom.Room.Floor));                    //level
                }
                else if (data == 3)
                {
                    return((short)baseroom.Room.Area);                    //area (???)
                }
                else if (data == 4)
                {
                    return((short)(room.Room.IsPool?1:0));                    //is pool
                }
                else
                {
                    throw new VMSimanticsException("Invalid room data!", context);
                }

            //throw new VMSimanticsException("Not implemented...");

            case VMVariableScope.NeighborInStackObject:     //24
                if (!context.VM.TS1)
                {
                    throw new VMSimanticsException("Only valid in TS1.", context);
                }
                var neighbor = Content.Content.Get().Neighborhood.GetNeighborByID(context.StackObjectID);
                var fam      = neighbor?.PersonData?.ElementAt((int)VMPersonDataVariable.TS1FamilyNumber);

                FAMI fami = null;
                if (fam != null)
                {
                    fami = Content.Content.Get().Neighborhood.GetFamily((ushort)fam.Value);
                }
                if (neighbor == null)
                {
                    return(0);
                }
                switch (data)
                {
                case 0:         //instance id
                    //find neighbour in the lot
                    return(context.VM.Context.ObjectQueries.Avatars.FirstOrDefault(x => x.Object.GUID == neighbor.GUID)?.ObjectID ?? 0);

                case 1:                                                                 //belongs in house
                    return((short)((context.VM.TS1State.CurrentFamily == fami) ? 1:0)); //uh, okay.

                case 2:                                                                 //person age
                    return(neighbor.PersonData?.ElementAt((int)VMPersonDataVariable.PersonsAge) ?? 0);

                case 3:         //relationship raw score
                                //to this person or from? what
                    return(0);  //unused in favor of primitive?

                case 4:         //relationship score
                    return(0);  //unused in favor of primitive?

                case 5:         //friend count
                    return((short)neighbor.Relationships.Count(n => {
                        if (n.Value[0] >= 50)
                        {
                            var othern = Content.Content.Get().Neighborhood.GetNeighborByID((short)n.Key);
                            if (othern != null)
                            {
                                List <short> orels;
                                if (othern.Relationships.TryGetValue(context.StackObjectID, out orels))
                                {
                                    return orels[0] >= 50;
                                }
                            }
                        }
                        return false;
                    }));        //interaction - nag friends TEST

                case 6:         //house number
                    return((short)(fami?.HouseNumber ?? 0));

                case 7:         //has telephone
                    return(1);

                case 8:         //has baby
                    return(0);

                case 9:         //family friend count
                    return((short)(fami?.FamilyFriends ?? 0));
                }
                throw new VMSimanticsException("Neighbor data out of bounds.", context);

            case VMVariableScope.Local:     //25
                return((short)context.Locals[data]);

            case VMVariableScope.Tuning:     //26
                return(GetTuningVariable(context.Callee, (ushort)data, context));

            case VMVariableScope.DynSpriteFlagForTempOfStackObject:     //27
                return(context.StackObject.IsDynamicSpriteFlagSet((ushort)context.Thread.TempRegisters[data]) ? (short)1 : (short)0);

            case VMVariableScope.TreeAdPersonalityVar:     //28
                throw new VMSimanticsException("Not implemented...", context);

            case VMVariableScope.TreeAdMin:     //29
                throw new VMSimanticsException("Not implemented...", context);

            case VMVariableScope.MyPersonDataByTemp:     //30
                return(((VMAvatar)context.Caller).GetPersonData((VMPersonDataVariable)(context.Thread.TempRegisters[data])));

            case VMVariableScope.StackObjectPersonDataByTemp:     //31
                return(((VMAvatar)context.StackObject).GetPersonData((VMPersonDataVariable)(context.Thread.TempRegisters[data])));

            case VMVariableScope.NeighborPersonData:     //32
                if (!context.VM.TS1)
                {
                    throw new VMSimanticsException("Only valid in TS1.", context);
                }
                return(Content.Content.Get().Neighborhood.GetNeighborByID(context.StackObjectID)?.PersonData?.ElementAt(data) ?? 0);

            case VMVariableScope.JobData:     //33 jobdata(temp0, temp1), used a few times to test if a person is at work but that isn't relevant for tso...
                if (!context.VM.TS1)
                {
                    throw new VMSimanticsException("Only valid in TS1.", context);
                }
                return(Content.Content.Get().Jobs.GetJobData((ushort)context.Thread.TempRegisters[0], context.Thread.TempRegisters[1], data));

            case VMVariableScope.NeighborhoodData: //34
                return(0);                         //tutorial values only

                throw new VMSimanticsException("Should not be used, but if this shows implement an empty shell to return ideal values.", context);

            case VMVariableScope.StackObjectFunction:     //35
                return((short)context.StackObject.EntryPoints[data].ActionFunction);

            case VMVariableScope.MyTypeAttr:     //36
                if (context.VM.TS1)
                {
                    return(Content.Content.Get().Neighborhood.GetTATT((context.Caller.MasterDefinition ?? context.Caller.Object.OBJ).TypeAttrGUID, data));
                }
                return(0);

            case VMVariableScope.StackObjectTypeAttr:     //37
                if (context.VM.TS1)
                {
                    return(Content.Content.Get().Neighborhood.GetTATT((context.StackObject.MasterDefinition ?? context.StackObject.Object.OBJ).TypeAttrGUID, data));
                }
                return(0);

            case VMVariableScope.NeighborsObjectDefinition:     //38
                if (!context.VM.TS1)
                {
                    throw new VMSimanticsException("Only valid in TS1.", context);
                }
                var neighbor2 = Content.Content.Get().Neighborhood.GetNeighborByID(context.StackObjectID);
                if (neighbor2 == null)
                {
                    return(0);
                }
                var objd = Content.Content.Get().WorldObjects.Get(neighbor2.GUID)?.OBJ;
                if (objd == null)
                {
                    return(0);
                }
                return(GetEntityDefinitionVar(objd, (VMOBJDVariable)data, context));

            case VMVariableScope.Unused:
                return(context.VM.TuningCache.GetLimit((VMMotive)data));

            case VMVariableScope.LocalByTemp:     //40
                return((short)context.Locals[context.Thread.TempRegisters[data]]);

            case VMVariableScope.StackObjectAttributeByTemp:     //41
                return(context.StackObject.GetAttribute((ushort)context.Thread.TempRegisters[data]));

            case VMVariableScope.TempXL:     //42
                //this needs a really intricate special case for specific operations.
                throw new VMSimanticsException("Caller function does not support TempXL!", context);

            case VMVariableScope.TSOStandardTime:     //44
                //return GetTSOStandardTime(data)
                var time = context.VM.Context.Clock.UTCNow;

                switch (data)
                {
                case 0:
                    return((short)time.Second);

                case 1:
                    return((short)time.Minute);

                case 2:
                    return((short)time.Hour);

                case 3:
                    return((short)time.Day);

                case 4:
                    return((short)time.Month);

                case 5:
                    return((short)time.Year);
                }
                ;
                return(0);

            case VMVariableScope.CityTime:     //43
            case VMVariableScope.GameTime:     //45
                switch (data)
                {
                case 0:
                    return((short)context.VM.Context.Clock.Seconds);

                case 1:
                    return((short)context.VM.Context.Clock.Minutes);

                case 2:
                    return((short)context.VM.Context.Clock.Hours);

                case 3:
                    return((short)context.VM.Context.Clock.TimeOfDay);

                case 4:
                    return((short)context.VM.Context.Clock.DayOfMonth);

                case 5:
                    return((short)context.VM.Context.Clock.Month);

                case 6:
                    return((short)context.VM.Context.Clock.Year);
                }
                ;
                break;

            case VMVariableScope.MyList:     //46 (man if only i knew what this meant)
                switch (data)
                {
                case 0: return(context.Caller.MyList.First.Value);        //is this allowed?

                case 1: return(context.Caller.MyList.Last.Value);

                case 2: return((short)context.Caller.MyList.Count);

                default: return(context.Caller.MyList.ElementAt(context.Thread.TempRegisters[0]));
                }

            case VMVariableScope.StackObjectList:     //47
                if (context.StackObject == null)
                {
                    return(0);
                }
                switch (data)
                {
                case 0: return(context.StackObject.MyList.First.Value);

                case 1: return(context.StackObject.MyList.Last.Value);

                case 2: return((short)context.StackObject.MyList.Count);

                default: return(context.StackObject.MyList.ElementAt(context.Thread.TempRegisters[0]));
                }

            case VMVariableScope.MoneyOverHead32Bit:     //48
                //we're poor... will need special case for this in expression like TempXL
                return(0);

            case VMVariableScope.MyLeadTileAttribute:     //49
                return(context.Caller.MultitileGroup.BaseObject.GetAttribute((ushort)data));

            case VMVariableScope.StackObjectLeadTileAttribute:     //50
                return(context.StackObject.MultitileGroup.BaseObject.GetAttribute((ushort)data));

            case VMVariableScope.MyLeadTile:     //51
                return(context.Caller.MultitileGroup.BaseObject.GetValue((VMStackObjectVariable)data));

            case VMVariableScope.StackObjectLeadTile:     //52
                return(context.StackObject.MultitileGroup.BaseObject.GetValue((VMStackObjectVariable)data));

            case VMVariableScope.StackObjectMasterDef:     //53
                //gets definition of the master tile of a multi tile object in the stack object.
                var masterDef = context.StackObject.MasterDefinition;
                return(GetEntityDefinitionVar((masterDef == null)?context.StackObject.Object.OBJ:masterDef, (VMOBJDVariable)data, context));

            case VMVariableScope.FeatureEnableLevel:     //54
                return(1);

            //all of them are enabled, dont really care right now

            case VMVariableScope.MyAvatarID:     //59
                uint myPID;
                if (data < 2)
                {
                    myPID = context.Caller.PersistID;
                }
                else
                {
                    myPID = context.StackObject.PersistID;
                }
                switch (data)
                {
                case 0:
                case 2:
                    return((short)myPID);

                case 1:
                case 3:
                    return((short)(myPID >> 16));

                default: return(0);
                }
            }
            throw new VMSimanticsException("Unknown get variable", context);
        }
예제 #18
0
        public static FAMI CreateFamily(string name, int count)
        {
            var neigh    = Content.Content.Get().Neighborhood;
            var families = neigh.MainResource.List <FAMI>() ?? new List <FAMI>();

            families = families.OrderBy(x => x.ChunkID).ToList();
            ushort newID = 0;

            for (int i = 0; i < families.Count; i++)
            {
                if (families[i].ChunkID == newID)
                {
                    newID++;
                }
                else
                {
                    break;
                }
            }

            var guids = new uint[count];

            for (int i = 0; i < count; i++)
            {
                guids[i] = GenerateGUID(guids);
            }

            var newFam = new FAMI()
            {
                ChunkLabel     = "",
                ChunkID        = newID,
                ChunkProcessed = true,
                ChunkType      = "FAMI",
                ChunkParent    = neigh.MainResource,
                AddedByPatch   = true,

                FamilyGUIDs  = guids,
                FamilyNumber = families.Max(x => x.FamilyNumber) + 1,
                Unknown      = 24,
                Budget       = 20000,
            };

            neigh.MainResource.AddChunk(newFam);

            var newFams = new FAMs()
            {
                ChunkLabel     = "",
                ChunkID        = newID,
                ChunkProcessed = true,
                ChunkType      = "FAMs",
                ChunkParent    = neigh.MainResource,
                AddedByPatch   = true,
            };

            newFams.InsertString(0, new STRItem()
            {
                Comment = "", Value = name
            });
            neigh.MainResource.AddChunk(newFams);

            return(newFam);
        }