Esempio n. 1
0
        public static RuinStructure GetRandom(RuinStructureType type, Alignment alignment)
        {
            if (list == null)
            {
                DebugConsole.Log("Loading ruin structures...");
                Load();
            }

            var matchingStructures = list.FindAll(rs => rs.Type.HasFlag(type) && rs.Alignment.HasFlag(alignment));

            if (!matchingStructures.Any())
            {
                return(null);
            }

            int totalCommonness = matchingStructures.Sum(m => m.commonness);

            int randomNumber = Rand.Int(totalCommonness + 1, false);

            foreach (RuinStructure ruinStructure in matchingStructures)
            {
                if (randomNumber <= ruinStructure.commonness)
                {
                    return(ruinStructure);
                }

                randomNumber -= ruinStructure.commonness;
            }

            return(null);
        }
Esempio n. 2
0
        public Line(Vector2 a, Vector2 b, RuinStructureType type)
        {
            Debug.Assert(a.X <= b.X);
            Debug.Assert(a.Y <= b.Y);

            A    = a;
            B    = b;
            Type = type;
        }
Esempio n. 3
0
        private List <RuinShape> GenerateStructures(List <VoronoiCell> caveCells, Rectangle ruinArea, bool mirror)
        {
            List <RuinShape> shapes = new List <RuinShape>(rooms);

            shapes.AddRange(corridors);

            if (mirror)
            {
                foreach (RuinShape shape in shapes)
                {
                    shape.MirrorX(ruinArea.Center.ToVector2());
                }
            }

            foreach (RuinShape leaf in shapes)
            {
                RuinStructureType wallType = RuinStructureType.Wall;

                if (!(leaf is BTRoom))
                {
                    wallType = RuinStructureType.CorridorWall;
                }
                //rooms further from the entrance are more likely to have hard-to-break walls
                else if (Rand.Range(0.0f, leaf.DistanceFromEntrance, Rand.RandSync.Server) > 1.5f)
                {
                    wallType = RuinStructureType.HeavyWall;
                }

                //generate walls  --------------------------------------------------------------
                foreach (Line wall in leaf.Walls)
                {
                    var structurePrefab = RuinStructure.GetRandom(wallType, leaf.GetLineAlignment(wall));
                    if (structurePrefab == null)
                    {
                        continue;
                    }

                    float radius = (wall.A.X == wall.B.X) ?
                                   (structurePrefab.Prefab as StructurePrefab).Size.X * 0.5f :
                                   (structurePrefab.Prefab as StructurePrefab).Size.Y * 0.5f;

                    Rectangle rect = new Rectangle(
                        (int)(wall.A.X - radius),
                        (int)(wall.B.Y + radius),
                        (int)((wall.B.X - wall.A.X) + radius * 2.0f),
                        (int)((wall.B.Y - wall.A.Y) + radius * 2.0f));

                    //cut a section off from both ends of a horizontal wall to get nicer looking corners
                    if (wall.A.Y == wall.B.Y)
                    {
                        rect.Inflate(-32, 0);
                        if (rect.Width < Submarine.GridSize.X)
                        {
                            continue;
                        }
                    }

                    var structure = new Structure(rect, structurePrefab.Prefab as StructurePrefab, null)
                    {
                        ShouldBeSaved = false
                    };
                    structure.SetCollisionCategory(Physics.CollisionLevel);
                }

                //generate backgrounds --------------------------------------------------------------
                var background = RuinStructure.GetRandom(RuinStructureType.Back, Alignment.Center);
                if (background == null)
                {
                    continue;
                }

                Rectangle backgroundRect = new Rectangle(leaf.Rect.X, leaf.Rect.Y + leaf.Rect.Height, leaf.Rect.Width, leaf.Rect.Height);

                new Structure(backgroundRect, (background.Prefab as StructurePrefab), null)
                {
                    ShouldBeSaved = false
                };

                var submarineBlocker = BodyFactory.CreateRectangle(GameMain.World,
                                                                   ConvertUnits.ToSimUnits(leaf.Rect.Width),
                                                                   ConvertUnits.ToSimUnits(leaf.Rect.Height),
                                                                   1, ConvertUnits.ToSimUnits(leaf.Center));

                submarineBlocker.IsStatic            = true;
                submarineBlocker.CollisionCategories = Physics.CollisionWall;
                submarineBlocker.CollidesWith        = Physics.CollisionWall;
            }

            List <RuinShape> doorlessRooms = new List <RuinShape>(shapes);

            //generate doors & sensors that close them -------------------------------------------------------------

            var sensorPrefab = MapEntityPrefab.Find("Alien Motion Sensor") as ItemPrefab;
            var wirePrefab   = MapEntityPrefab.Find("Wire") as ItemPrefab;

            foreach (Corridor corridor in corridors)
            {
                var doorPrefab = RuinStructure.GetRandom(corridor.IsHorizontal ? RuinStructureType.Door : RuinStructureType.Hatch, Alignment.Center);
                if (doorPrefab == null)
                {
                    continue;
                }

                //find all walls that are parallel to the corridor
                var suitableWalls = corridor.IsHorizontal ?
                                    corridor.Walls.FindAll(c => c.A.Y == c.B.Y) : corridor.Walls.FindAll(c => c.A.X == c.B.X);

                if (!suitableWalls.Any())
                {
                    continue;
                }

                doorlessRooms.Remove(corridor);
                Vector2 doorPos = corridor.Center;

                //choose a random wall to place the door next to
                var wall = suitableWalls[Rand.Int(suitableWalls.Count, Rand.RandSync.Server)];
                if (corridor.IsHorizontal)
                {
                    doorPos.X = (wall.A.X + wall.B.X) / 2.0f;
                }
                else
                {
                    doorPos.Y = (wall.A.Y + wall.B.Y) / 2.0f;
                }

                var door = new Item(doorPrefab.Prefab as ItemPrefab, doorPos, null)
                {
                    ShouldBeSaved = false
                };

                door.GetComponent <Items.Components.Door>().IsOpen = Rand.Range(0.0f, 1.0f, Rand.RandSync.Server) < 0.8f;

                if (sensorPrefab == null || wirePrefab == null)
                {
                    continue;
                }

                var sensorRoom = corridor.ConnectedRooms.FirstOrDefault(r => r != null && rooms.Contains(r));
                if (sensorRoom == null)
                {
                    continue;
                }

                var sensor = new Item(sensorPrefab, new Vector2(
                                          Rand.Range(sensorRoom.Rect.X, sensorRoom.Rect.Right, Rand.RandSync.Server),
                                          Rand.Range(sensorRoom.Rect.Y, sensorRoom.Rect.Bottom, Rand.RandSync.Server)), null)
                {
                    ShouldBeSaved = false
                };

                var wire = new Item(wirePrefab, sensorRoom.Center, null).GetComponent <Items.Components.Wire>();
                wire.Item.ShouldBeSaved = false;

                var conn1 = door.Connections.Find(c => c.Name == "set_state");
                conn1.AddLink(0, wire);
                wire.Connect(conn1, false);

                var conn2 = sensor.Connections.Find(c => c.Name == "state_out");
                conn2.AddLink(0, wire);
                wire.Connect(conn2, false);
            }


            //generate props --------------------------------------------------------------
            for (int i = 0; i < shapes.Count * 2; i++)
            {
                Alignment[] alignments = new Alignment[] { Alignment.Top, Alignment.Bottom, Alignment.Right, Alignment.Left, Alignment.Center };

                var prop = RuinStructure.GetRandom(RuinStructureType.Prop, alignments[Rand.Int(alignments.Length, Rand.RandSync.Server)]);
                if (prop == null)
                {
                    continue;
                }

                Vector2 size = (prop.Prefab is StructurePrefab) ? ((StructurePrefab)prop.Prefab).Size : Vector2.Zero;

                //if the prop is placed at the center of the room, we have to use a room without a door (because they're also placed at the center)
                var shape = prop.Alignment.HasFlag(Alignment.Center) ?
                            doorlessRooms[Rand.Int(doorlessRooms.Count, Rand.RandSync.Server)] :
                            shapes[Rand.Int(shapes.Count, Rand.RandSync.Server)];

                Vector2 position = shape.Rect.Center.ToVector2();
                if (prop.Alignment.HasFlag(Alignment.Top))
                {
                    position = new Vector2(Rand.Range(shape.Rect.X + size.X, shape.Rect.Right - size.X, Rand.RandSync.Server), shape.Rect.Bottom - 64);
                }
                else if (prop.Alignment.HasFlag(Alignment.Bottom))
                {
                    position = new Vector2(Rand.Range(shape.Rect.X + size.X, shape.Rect.Right - size.X, Rand.RandSync.Server), shape.Rect.Top + 64);
                }
                else if (prop.Alignment.HasFlag(Alignment.Right))
                {
                    position = new Vector2(shape.Rect.Right - 64, Rand.Range(shape.Rect.Y + size.X, shape.Rect.Bottom - size.Y, Rand.RandSync.Server));
                }
                else if (prop.Alignment.HasFlag(Alignment.Left))
                {
                    position = new Vector2(shape.Rect.X + 64, Rand.Range(shape.Rect.Y + size.X, shape.Rect.Bottom - size.Y, Rand.RandSync.Server));
                }

                if (prop.Prefab is ItemPrefab)
                {
                    new Item((ItemPrefab)prop.Prefab, position, null);
                }
                else
                {
                    new Structure(new Rectangle(
                                      (int)(position.X - size.X / 2.0f), (int)(position.Y + size.Y / 2.0f),
                                      (int)size.X, (int)size.Y),
                                  prop.Prefab as StructurePrefab, null)
                    {
                        ShouldBeSaved = false
                    };
                }
            }

            return(shapes);
        }