Ejemplo n.º 1
0
        /// <summary>
        /// Instantiates level data using the properties of the connection (seed, size, difficulty)
        /// </summary>
        public LevelData(LocationConnection locationConnection)
        {
            Seed             = locationConnection.Locations[0].BaseName + locationConnection.Locations[1].BaseName;
            Biome            = locationConnection.Biome;
            Type             = LevelType.LocationConnection;
            GenerationParams = LevelGenerationParams.GetRandom(Seed, LevelType.LocationConnection, Biome);
            Difficulty       = locationConnection.Difficulty;

            float sizeFactor = MathUtils.InverseLerp(
                MapGenerationParams.Instance.SmallLevelConnectionLength,
                MapGenerationParams.Instance.LargeLevelConnectionLength,
                locationConnection.Length);
            int width = (int)MathHelper.Lerp(GenerationParams.MinWidth, GenerationParams.MaxWidth, sizeFactor);

            Size = new Point(
                (int)MathUtils.Round(width, Level.GridCellSize),
                (int)MathUtils.Round(GenerationParams.Height, Level.GridCellSize));

            var rand = new MTRandom(ToolBox.StringToInt(Seed));

            InitialDepth = (int)MathHelper.Lerp(GenerationParams.InitialDepthMin, GenerationParams.InitialDepthMax, (float)rand.NextDouble());

            HasBeaconStation = rand.NextDouble() < locationConnection.Locations.Select(l => l.Type.BeaconStationChance).Max();
            IsBeaconActive   = false;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Instantiates level data using the properties of the connection (seed, size, difficulty)
        /// </summary>
        public LevelData(LocationConnection locationConnection)
        {
            Seed             = locationConnection.Locations[0].BaseName + locationConnection.Locations[1].BaseName;
            Biome            = locationConnection.Biome;
            Type             = LevelType.LocationConnection;
            GenerationParams = LevelGenerationParams.GetRandom(Seed, LevelType.LocationConnection, Biome);
            Difficulty       = locationConnection.Difficulty;

            float sizeFactor = MathUtils.InverseLerp(
                MapGenerationParams.Instance.SmallLevelConnectionLength,
                MapGenerationParams.Instance.LargeLevelConnectionLength,
                locationConnection.Length);
            int width = (int)MathHelper.Lerp(GenerationParams.MinWidth, GenerationParams.MaxWidth, sizeFactor);

            Size = new Point(
                (int)MathUtils.Round(width, Level.GridCellSize),
                (int)MathUtils.Round(GenerationParams.Height, Level.GridCellSize));

            var rand = new MTRandom(ToolBox.StringToInt(Seed));

            InitialDepth = (int)MathHelper.Lerp(GenerationParams.InitialDepthMin, GenerationParams.InitialDepthMax, (float)rand.NextDouble());

            //minimum difficulty of the level before hunting grounds can appear
            float huntingGroundsDifficultyThreshold = 25;
            //probability of hunting grounds appearing in 100% difficulty levels
            float maxHuntingGroundsProbability = 0.3f;

            HasHuntingGrounds = OriginallyHadHuntingGrounds = rand.NextDouble() < MathUtils.InverseLerp(huntingGroundsDifficultyThreshold, 100.0f, Difficulty) * maxHuntingGroundsProbability;

            HasBeaconStation = !HasHuntingGrounds && rand.NextDouble() < locationConnection.Locations.Select(l => l.Type.BeaconStationChance).Max();
            IsBeaconActive   = false;
        }
Ejemplo n.º 3
0
        public void SelectLocation(Location location, LocationConnection connection)
        {
            GUIComponent locationPanel = bottomPanel[(int)PanelTab.Map].GetChild("selectedlocation");

            if (locationPanel != null)
            {
                bottomPanel[(int)PanelTab.Map].RemoveChild(locationPanel);
            }

            locationPanel          = new GUIFrame(new Rectangle(0, 0, 250, 190), Color.Transparent, Alignment.TopRight, null, bottomPanel[(int)PanelTab.Map]);
            locationPanel.UserData = "selectedlocation";

            if (location == null)
            {
                return;
            }

            new GUITextBlock(new Rectangle(0, 0, 250, 0), location.Name, "", Alignment.TopLeft, Alignment.TopCenter, locationPanel, true, GUI.LargeFont);

            if (GameMain.GameSession.Map.SelectedConnection != null && GameMain.GameSession.Map.SelectedConnection.Mission != null)
            {
                var mission = GameMain.GameSession.Map.SelectedConnection.Mission;

                new GUITextBlock(new Rectangle(0, 80, 0, 20), "Mission: " + mission.Name, "", locationPanel);

                new GUITextBlock(new Rectangle(0, 100, 0, 20), "Reward: " + mission.Reward + " credits", "", locationPanel);

                new GUITextBlock(new Rectangle(0, 130, 0, 0), mission.Description, "", locationPanel, true);
            }

            startButton.Enabled = true;

            selectedLevel = connection.Level;
        }
Ejemplo n.º 4
0
        private void AssignBiomes()
        {
            List <LocationConnection> biomeSeeds = new List <LocationConnection>();

            List <Biome> centerBiomes = LevelGenerationParams.GetBiomes().FindAll(b => b.Placement.HasFlag(Biome.MapPlacement.Center));

            if (centerBiomes.Count > 0)
            {
                Vector2 mapCenter = new Vector2(locations.Sum(l => l.MapPosition.X), locations.Sum(l => l.MapPosition.Y)) / locations.Count;
                foreach (Biome centerBiome in centerBiomes)
                {
                    LocationConnection closestConnection = null;
                    float closestDist = float.PositiveInfinity;
                    foreach (LocationConnection connection in connections)
                    {
                        if (connection.Biome != null)
                        {
                            continue;
                        }

                        float dist = Vector2.Distance(connection.CenterPos, mapCenter);
                        if (closestConnection == null || dist < closestDist)
                        {
                            closestConnection = connection;
                            closestDist       = dist;
                        }
                    }

                    closestConnection.Biome = centerBiome;
                    biomeSeeds.Add(closestConnection);
                }
            }

            List <Biome> edgeBiomes = LevelGenerationParams.GetBiomes().FindAll(b => b.Placement.HasFlag(Biome.MapPlacement.Edge));

            if (edgeBiomes.Count > 0)
            {
                List <LocationConnection> edges = GetMapEdges();
                foreach (LocationConnection edge in edges)
                {
                    edge.Biome = edgeBiomes[Rand.Range(0, edgeBiomes.Count, Rand.RandSync.Server)];
                }
            }

            List <Biome> randomBiomes = LevelGenerationParams.GetBiomes().FindAll(b => b.Placement.HasFlag(Biome.MapPlacement.Random));

            foreach (Biome biome in randomBiomes)
            {
                LocationConnection seed = connections[0];
                while (seed.Biome != null)
                {
                    seed = connections[Rand.Range(0, connections.Count, Rand.RandSync.Server)];
                }
                seed.Biome = biome;
                biomeSeeds.Add(seed);
            }

            ExpandBiomes(biomeSeeds);
        }
        private void ConnectSecondaryNodes(SecondaryNode node1, SecondaryNode node2)
        {
            LocationConnection newConnection = new LocationConnection(node1, node2);

            connections.Add(newConnection);
            node1.connections.Add(newConnection);
            node2.connections.Add(newConnection);
        }
        private void ConnectPrimaryNodes(PrimaryNode node1, PrimaryNode node2)
        {
            LocationConnection newConnection = new LocationConnection(node1, node2);

            connections.Add(newConnection);
            node1.connections.Add(newConnection);
            node2.connections.Add(newConnection);
        }
Ejemplo n.º 7
0
 private void NotifyUnlock(LocationConnection connection)
 {
     foreach (Client client in GameMain.Server.ConnectedClients)
     {
         IWriteMessage outmsg = new WriteOnlyMessage();
         outmsg.Write((byte)ServerPacketHeader.EVENTACTION);
         outmsg.Write((byte)EventManager.NetworkEventType.UNLOCKPATH);
         outmsg.Write((UInt16)GameMain.GameSession.Map.Connections.IndexOf(connection));
         GameMain.Server.ServerPeer.Send(outmsg, client.Connection, DeliveryMethod.Reliable);
     }
 }
        //DEBUG

        /*foreach (GraphEdge edge in graphEdges)
         * {
         *  Location newLocation1;
         *  Location newLocation2;
         *
         *  if ((edge.node1 != null && edge.node2 != null) && (edge.node1.group == edge.node2.group))
         *  {
         *      if (primaryNodes.Any(n => n.mapPosition == edge.node1.mapPosition) && primaryNodes.Any(n => n.mapPosition == edge.node2.mapPosition))
         *      {
         *          if (!locations.Any(l => l.MapPosition == edge.node1.mapPosition))
         *          {
         *              newLocation1 = Location.CreateRandom(edge.node1.mapPosition);
         *              locations.Add(newLocation1);
         *          }
         *          else
         *              newLocation1 = locations.Find(l => l.MapPosition == edge.node1.mapPosition);
         *          if (!locations.Any(l => l.MapPosition == edge.node2.mapPosition))
         *          {
         *              newLocation2 = Location.CreateRandom(edge.node2.mapPosition);
         *              locations.Add(newLocation2);
         *          }
         *          else
         *              newLocation2 = locations.Find(l => l.MapPosition == edge.node2.mapPosition);
         *
         *          //connections.Add(new LocationConnection(newLocation1, newLocation2));
         *          ConnectLocations(newLocation1, newLocation2);
         *      }
         *  }
         * }*/

        private LocationConnection ConnectLocations(Location location1, Location location2)
        {
            LocationConnection newConnection = new LocationConnection(location1, location2);

            connections.Add(newConnection);
            location1.Connections.Add(newConnection);
            location2.Connections.Add(newConnection);

            newConnection.primaryNodes = new PrimaryNode[2];

            return(newConnection);
        }
Ejemplo n.º 9
0
        public void SelectLocation(Location location)
        {
            if (!locations.Contains(location))
            {
                DebugConsole.ThrowError("Failed to select a location. " + location.Name + " not found in the map.");
                return;
            }

            selectedLocation   = location;
            selectedConnection = connections.Find(c => c.Locations.Contains(currentLocation) && c.Locations.Contains(selectedLocation));
            OnLocationSelected?.Invoke(selectedLocation, selectedConnection);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Instantiates level data using the properties of the connection (seed, size, difficulty)
        /// </summary>
        public LevelData(LocationConnection locationConnection)
        {
            Seed             = locationConnection.Locations[0].BaseName + locationConnection.Locations[1].BaseName;
            Biome            = locationConnection.Biome;
            Type             = LevelType.LocationConnection;
            GenerationParams = LevelGenerationParams.GetRandom(Seed, LevelType.LocationConnection, Biome);
            Difficulty       = locationConnection.Difficulty;

            float sizeFactor = MathUtils.InverseLerp(
                MapGenerationParams.Instance.SmallLevelConnectionLength,
                MapGenerationParams.Instance.LargeLevelConnectionLength,
                locationConnection.Length);
            int width = (int)MathHelper.Lerp(GenerationParams.MinWidth, GenerationParams.MaxWidth, sizeFactor);

            Size = new Point(
                (int)MathUtils.Round(width, Level.GridCellSize),
                (int)MathUtils.Round(GenerationParams.Height, Level.GridCellSize));
        }
Ejemplo n.º 11
0
        public void Update(float deltaTime, Rectangle rect, float scale = 1.0f)
        {
            Vector2 rectCenter = new Vector2(rect.Center.X, rect.Center.Y);
            Vector2 offset     = -currentLocation.MapPosition;

            float maxDist     = 20.0f;
            float closestDist = 0.0f;

            highlightedLocation = null;
            for (int i = 0; i < locations.Count; i++)
            {
                Location location = locations[i];
                Vector2  pos      = rectCenter + (location.MapPosition + offset) * scale;

                if (!rect.Contains(pos))
                {
                    continue;
                }

                float dist = Vector2.Distance(PlayerInput.MousePosition, pos);
                if (dist < maxDist && (highlightedLocation == null || dist < closestDist))
                {
                    closestDist         = dist;
                    highlightedLocation = location;
                }
            }

            foreach (LocationConnection connection in connections)
            {
                if (highlightedLocation != currentLocation &&
                    connection.Locations.Contains(highlightedLocation) && connection.Locations.Contains(currentLocation))
                {
                    if (PlayerInput.LeftButtonClicked() &&
                        selectedLocation != highlightedLocation && highlightedLocation != null)
                    {
                        selectedConnection = connection;
                        selectedLocation   = highlightedLocation;
                        GameMain.LobbyScreen.SelectLocation(highlightedLocation, connection);
                    }
                }
            }
        }
Ejemplo n.º 12
0
        public void SelectLocation(Location location, LocationConnection connection)
        {
            locationInfoContainer.ClearChildren();

            if (location == null)
            {
                return;
            }

            var titleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), locationInfoContainer.RectTransform, Anchor.TopCenter), location.Name, font: GUI.LargeFont);

            Sprite portrait = location.Type.Background;

            new GUIImage(new RectTransform(
                             new Point(locationInfoContainer.Rect.Width, (int)(portrait.size.Y * (locationInfoContainer.Rect.Width / portrait.size.X))),
                             locationInfoContainer.RectTransform), portrait, scaleToFit: true);

            if (GameMain.GameSession.Map.SelectedConnection != null && GameMain.GameSession.Map.SelectedConnection.Mission != null)
            {
                var mission = GameMain.GameSession.Map.SelectedConnection.Mission;

                new GUITextBlock(
                    new RectTransform(new Vector2(1.0f, 0.05f), locationInfoContainer.RectTransform, Anchor.TopCenter),
                    TextManager.Get("Mission") + ": " + mission.Name);
                new GUITextBlock(
                    new RectTransform(new Vector2(1.0f, 0.05f), locationInfoContainer.RectTransform, Anchor.TopCenter),
                    TextManager.Get("Reward").Replace("[reward]", mission.Reward.ToString()));
                new GUITextBlock(
                    new RectTransform(new Vector2(1.0f, 0.0f), locationInfoContainer.RectTransform, Anchor.TopCenter),
                    mission.Description, wrap: true);
            }

            if (startButton != null)
            {
                startButton.Enabled = true;
            }

            selectedLevel = connection?.Level;

            OnLocationSelected?.Invoke(location, connection);
        }
Ejemplo n.º 13
0
        public void SelectLocation(int index)
        {
            if (index == -1)
            {
                selectedLocation   = null;
                selectedConnection = null;

                OnLocationSelected?.Invoke(null, null);
                return;
            }

            if (index < 0 || index >= locations.Count)
            {
                DebugConsole.ThrowError("Location index out of bounds");
                return;
            }

            selectedLocation   = locations[index];
            selectedConnection = connections.Find(c => c.Locations.Contains(currentLocation) && c.Locations.Contains(selectedLocation));
            OnLocationSelected?.Invoke(selectedLocation, selectedConnection);
        }
Ejemplo n.º 14
0
        public void SelectLocation(Location location, LocationConnection connection)
        {
            GUIComponent locationPanel = tabs[(int)Tab.Map].GetChild("selectedlocation");

            if (locationPanel != null) tabs[(int)Tab.Map].RemoveChild(locationPanel);

            locationPanel = new GUIFrame(new Rectangle(0, 0, 250, 190), Color.Transparent, Alignment.TopRight, null, tabs[(int)Tab.Map]);
            locationPanel.UserData = "selectedlocation";

            if (location == null) return;

            GUITextBlock titleText;

            if (GameMain.Server != null || GameMain.Client != null)
            {
                titleText = new GUITextBlock(new Rectangle(0, 10, 250, 0), location.Name, "", Alignment.TopLeft, Alignment.TopCenter, locationPanel, true, GUI.LargeFont);
            }
            else
            {
                titleText = new GUITextBlock(new Rectangle(0, 0, 250, 0), location.Name, "", Alignment.TopLeft, Alignment.TopCenter, locationPanel, true, GUI.LargeFont);
            }


            if (GameMain.GameSession.Map.SelectedConnection != null && GameMain.GameSession.Map.SelectedConnection.Mission != null)
            {
                var mission = GameMain.GameSession.Map.SelectedConnection.Mission;

                new GUITextBlock(new Rectangle(0, titleText.Rect.Height + 20, 0, 20), TextManager.Get("Mission") + ": " + mission.Name, "", locationPanel);
                new GUITextBlock(new Rectangle(0, titleText.Rect.Height + 40, 0, 20), TextManager.Get("Reward") + ": " + mission.Reward + " " + TextManager.Get("Credits"), "", locationPanel);
                new GUITextBlock(new Rectangle(0, titleText.Rect.Height + 70, 0, 0), mission.Description, "", Alignment.TopLeft, Alignment.TopLeft, locationPanel, true, GUI.SmallFont);
            }

            if (startButton != null) startButton.Enabled = true;

            selectedLevel = connection.Level;

            OnLocationSelected?.Invoke(location, connection);
        }
Ejemplo n.º 15
0
        public void SelectLocation(Location location, LocationConnection connection)
        {
            missionTickBoxes.Clear();
            missionRewardTexts.Clear();
            locationInfoPanel.ClearChildren();
            //don't select the map panel if we're looking at some other tab
            if (selectedTab == CampaignMode.InteractionType.Map)
            {
                SelectTab(CampaignMode.InteractionType.Map);
                locationInfoPanel.Visible = location != null;
            }

            Location prevSelectedLocation  = selectedLocation;
            float    prevMissionListScroll = missionList?.BarScroll ?? 0.0f;

            selectedLocation = location;
            if (location == null)
            {
                return;
            }

            int padding = GUI.IntScale(20);

            var content = new GUILayoutGroup(new RectTransform(locationInfoPanel.Rect.Size - new Point(padding * 2), locationInfoPanel.RectTransform, Anchor.Center), childAnchor: Anchor.TopRight)
            {
                Stretch         = true,
                RelativeSpacing = 0.02f,
            };

            new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), location.Name, font: GUI.LargeFont)
            {
                AutoScaleHorizontal = true
            };
            new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), location.Type.Name, font: GUI.SubHeadingFont);

            Sprite portrait = location.Type.GetPortrait(location.PortraitId);

            portrait.EnsureLazyLoaded();

            var portraitContainer = new GUICustomComponent(new RectTransform(new Vector2(1.0f, 0.3f), content.RectTransform), onDraw: (sb, customComponent) =>
            {
                portrait.Draw(sb, customComponent.Rect.Center.ToVector2(), Color.Gray, portrait.size / 2, scale: Math.Max(customComponent.Rect.Width / portrait.size.X, customComponent.Rect.Height / portrait.size.Y));
            })
            {
                HideElementsOutsideFrame = true
            };

            var textContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), portraitContainer.RectTransform, Anchor.Center))
            {
                RelativeSpacing = 0.05f
            };

            if (connection?.LevelData != null)
            {
                var biomeLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), textContent.RectTransform),
                                                  TextManager.Get("Biome", fallBackTag: "location"), font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft);
                new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), biomeLabel.RectTransform), connection.Biome.DisplayName, textAlignment: Alignment.CenterRight);

                var difficultyLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), textContent.RectTransform),
                                                       TextManager.Get("LevelDifficulty"), font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft);
                new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), difficultyLabel.RectTransform), ((int)connection.LevelData.Difficulty) + " %", textAlignment: Alignment.CenterRight);

                if (connection.LevelData.HasBeaconStation)
                {
                    var    beaconStationContent = new GUILayoutGroup(new RectTransform(biomeLabel.RectTransform.NonScaledSize, textContent.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
                    string style = connection.LevelData.IsBeaconActive ? "BeaconStationActive" : "BeaconStationInactive";
                    var    icon  = new GUIImage(new RectTransform(new Point((int)(beaconStationContent.Rect.Height * 1.2f)), beaconStationContent.RectTransform),
                                                style, scaleToFit: true)
                    {
                        Color      = MapGenerationParams.Instance.IndicatorColor,
                        HoverColor = Color.Lerp(MapGenerationParams.Instance.IndicatorColor, Color.White, 0.5f),
                        ToolTip    = TextManager.Get(connection.LevelData.IsBeaconActive ? "BeaconStationActiveTooltip" : "BeaconStationInactiveTooltip")
                    };
                    new GUITextBlock(new RectTransform(Vector2.One, beaconStationContent.RectTransform),
                                     TextManager.Get("submarinetype.beaconstation", fallBackTag: "beaconstationsonarlabel"), font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft)
                    {
                        Padding = Vector4.Zero,
                        ToolTip = icon.ToolTip
                    };
                }
                if (connection.LevelData.HasHuntingGrounds)
                {
                    var huntingGroundsContent = new GUILayoutGroup(new RectTransform(biomeLabel.RectTransform.NonScaledSize, textContent.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
                    var icon = new GUIImage(new RectTransform(new Point((int)(huntingGroundsContent.Rect.Height * 1.5f)), huntingGroundsContent.RectTransform),
                                            "HuntingGrounds", scaleToFit: true)
                    {
                        Color      = MapGenerationParams.Instance.IndicatorColor,
                        HoverColor = Color.Lerp(MapGenerationParams.Instance.IndicatorColor, Color.White, 0.5f),
                        ToolTip    = TextManager.Get("HuntingGroundsTooltip")
                    };
                    new GUITextBlock(new RectTransform(Vector2.One, huntingGroundsContent.RectTransform),
                                     TextManager.Get("missionname.huntinggrounds"), font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft)
                    {
                        Padding = Vector4.Zero,
                        ToolTip = icon.ToolTip
                    };
                }
            }

            missionList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.4f), content.RectTransform))
            {
                Spacing = (int)(5 * GUI.yScale)
            };
            missionList.OnSelected = (GUIComponent selected, object userdata) =>
            {
                var tickBox = selected.FindChild(c => c is GUITickBox, recursive: true) as GUITickBox;
                if (GUI.MouseOn == tickBox)
                {
                    return(false);
                }
                if (tickBox != null)
                {
                    if (Campaign.AllowedToManageCampaign() && tickBox.Enabled)
                    {
                        tickBox.Selected = !tickBox.Selected;
                    }
                }
                return(true);
            };

            SelectedLevel = connection?.LevelData;
            Location currentDisplayLocation = Campaign.GetCurrentDisplayLocation();

            if (connection != null && connection.Locations.Contains(currentDisplayLocation))
            {
                List <Mission> availableMissions = currentDisplayLocation.GetMissionsInConnection(connection).ToList();
                if (!availableMissions.Contains(null))
                {
                    availableMissions.Insert(0, null);
                }

                missionList.Content.ClearChildren();

                foreach (Mission mission in availableMissions)
                {
                    var missionPanel = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), missionList.Content.RectTransform), style: null)
                    {
                        UserData = mission
                    };
                    var missionTextContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), missionPanel.RectTransform, Anchor.Center))
                    {
                        Stretch         = true,
                        CanBeFocused    = true,
                        AbsoluteSpacing = GUI.IntScale(5)
                    };

                    var missionName = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), mission?.Name ?? TextManager.Get("NoMission"), font: GUI.SubHeadingFont, wrap: true);
                    // missionName.RectTransform.MinSize = new Point(0, (int)(missionName.Rect.Height * 1.5f));
                    if (mission != null)
                    {
                        var tickBox = new GUITickBox(new RectTransform(Vector2.One * 0.9f, missionName.RectTransform, anchor: Anchor.CenterLeft, scaleBasis: ScaleBasis.Smallest)
                        {
                            AbsoluteOffset = new Point((int)missionName.Padding.X, 0)
                        }, label: string.Empty)
                        {
                            UserData = mission,
                            Selected = Campaign.Map.CurrentLocation?.SelectedMissions.Contains(mission) ?? false
                        };
                        tickBox.RectTransform.MinSize     = new Point(tickBox.Rect.Height, 0);
                        tickBox.RectTransform.IsFixedSize = true;
                        tickBox.Enabled     = Campaign.AllowedToManageCampaign();
                        tickBox.OnSelected += (GUITickBox tb) =>
                        {
                            if (!Campaign.AllowedToManageCampaign())
                            {
                                return(false);
                            }

                            if (tb.Selected)
                            {
                                Campaign.Map.CurrentLocation.SelectMission(mission);
                            }
                            else
                            {
                                Campaign.Map.CurrentLocation.DeselectMission(mission);
                            }

                            foreach (GUITextBlock rewardText in missionRewardTexts)
                            {
                                Mission otherMission = rewardText.UserData as Mission;
                                rewardText.SetRichText(otherMission.GetMissionRewardText(Submarine.MainSub));
                            }

                            UpdateMaxMissions(connection.OtherLocation(currentDisplayLocation));

                            if ((Campaign is MultiPlayerCampaign multiPlayerCampaign) && !multiPlayerCampaign.SuppressStateSending &&
                                Campaign.AllowedToManageCampaign())
                            {
                                GameMain.Client?.SendCampaignState();
                            }
                            return(true);
                        };
                        missionTickBoxes.Add(tickBox);

                        GUILayoutGroup difficultyIndicatorGroup = null;
                        if (mission.Difficulty.HasValue)
                        {
                            difficultyIndicatorGroup = new GUILayoutGroup(new RectTransform(Vector2.One * 0.9f, missionName.RectTransform, anchor: Anchor.CenterRight, scaleBasis: ScaleBasis.Smallest)
                            {
                                AbsoluteOffset = new Point((int)missionName.Padding.Z, 0)
                            },
                                                                          isHorizontal: true, childAnchor: Anchor.CenterRight)
                            {
                                AbsoluteSpacing = 1,
                                UserData        = "difficulty"
                            };
                            var difficultyColor = mission.GetDifficultyColor();
                            for (int i = 0; i < mission.Difficulty; i++)
                            {
                                new GUIImage(new RectTransform(Vector2.One, difficultyIndicatorGroup.RectTransform, scaleBasis: ScaleBasis.Smallest)
                                {
                                    IsFixedSize = true
                                }, "DifficultyIndicator", scaleToFit: true)
                                {
                                    Color         = difficultyColor,
                                    SelectedColor = difficultyColor,
                                    HoverColor    = difficultyColor
                                };
                            }
                        }

                        float extraPadding  = 0;// 0.8f * tickBox.Rect.Width;
                        float extraZPadding = difficultyIndicatorGroup != null ? mission.Difficulty.Value * (difficultyIndicatorGroup.Children.First().Rect.Width + difficultyIndicatorGroup.AbsoluteSpacing) : 0;
                        missionName.Padding = new Vector4(missionName.Padding.X + tickBox.Rect.Width * 1.2f + extraPadding,
                                                          missionName.Padding.Y,
                                                          missionName.Padding.Z + extraZPadding + extraPadding,
                                                          missionName.Padding.W);
                        missionName.CalculateHeightFromText();

                        //spacing
                        new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform)
                        {
                            MinSize = new Point(0, GUI.IntScale(10))
                        }, style: null);

                        var rewardText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), mission.GetMissionRewardText(Submarine.MainSub), wrap: true, parseRichText: true)
                        {
                            UserData = mission
                        };
                        missionRewardTexts.Add(rewardText);

                        string reputationText = mission.GetReputationRewardText(mission.Locations[0]);
                        new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), reputationText, wrap: true, parseRichText: true);

                        new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), mission.Description, wrap: true, parseRichText: true);
                    }
                    missionPanel.RectTransform.MinSize = new Point(0, (int)(missionTextContent.Children.Sum(c => c.Rect.Height + missionTextContent.AbsoluteSpacing) / missionTextContent.RectTransform.RelativeSize.Y) + GUI.IntScale(0));
                    foreach (GUIComponent child in missionTextContent.Children)
                    {
                        if (child is GUITextBlock textBlock)
                        {
                            textBlock.Color             = textBlock.SelectedColor = textBlock.HoverColor = Color.Transparent;
                            textBlock.SelectedTextColor = textBlock.HoverTextColor = textBlock.TextColor;
                        }
                    }
                    missionPanel.OnAddedToGUIUpdateList = (c) =>
                    {
                        missionTextContent.Children.ForEach(child => child.State = c.State);
                        if (missionTextContent.FindChild("difficulty", recursive: true) is GUILayoutGroup group)
                        {
                            group.State = c.State;
                        }
                    };

                    if (mission != availableMissions.Last())
                    {
                        new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), missionList.Content.RectTransform), style: "HorizontalLine")
                        {
                            CanBeFocused = false
                        };
                    }
                }
                if (prevSelectedLocation == selectedLocation)
                {
                    missionList.BarScroll = prevMissionListScroll;
                    missionList.UpdateDimensions();
                    missionList.UpdateScrollBarSize();
                }
            }
            var destination = connection.OtherLocation(currentDisplayLocation);

            UpdateMaxMissions(destination);

            var buttonArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform), isHorizontal: true);

            new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), buttonArea.RectTransform), "", font: GUI.Style.SubHeadingFont)
            {
                TextGetter = () =>
                {
                    return(TextManager.AddPunctuation(':', TextManager.Get("Missions"), $"{Campaign.NumberOfMissionsAtLocation(destination)}/{Campaign.Settings.MaxMissionCount}"));
                }
            };

            StartButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), buttonArea.RectTransform),
                                        TextManager.Get("StartCampaignButton"), style: "GUIButtonLarge")
            {
                OnClicked = (GUIButton btn, object obj) =>
                {
                    if (missionList.Content.FindChild(c => c is GUITickBox tickBox && tickBox.Selected, recursive: true) == null &&
                        missionList.Content.Children.Any(c => c.UserData is Mission))
                    {
                        var noMissionVerification = new GUIMessageBox(string.Empty, TextManager.Get("nomissionprompt"), new string[] { TextManager.Get("yes"), TextManager.Get("no") });
                        noMissionVerification.Buttons[0].OnClicked = (btn, userdata) =>
                        {
                            StartRound?.Invoke();
                            noMissionVerification.Close();
                            return(true);
                        };
                        noMissionVerification.Buttons[1].OnClicked = noMissionVerification.Close;
                    }
Ejemplo n.º 16
0
        private void Generate()
        {
            connections.Clear();
            Locations.Clear();

            GenerateNoiseMap(generationParams.NoiseOctaves, generationParams.NoisePersistence);

            List <Vector2> sites     = new List <Vector2>();
            float          mapRadius = size / 2;
            Vector2        mapCenter = new Vector2(mapRadius, mapRadius);

            float locationRadius = mapRadius * generationParams.LocationRadius;

            for (float x = mapCenter.X - locationRadius; x < mapCenter.X + locationRadius; x += generationParams.VoronoiSiteInterval)
            {
                for (float y = mapCenter.Y - locationRadius; y < mapCenter.Y + locationRadius; y += generationParams.VoronoiSiteInterval)
                {
                    float noiseVal = Noise[(int)(x / size * generationParams.NoiseResolution), (int)(y / size * generationParams.NoiseResolution)];
                    if (Rand.Range(generationParams.VoronoiSitePlacementMinVal, 1.0f, Rand.RandSync.Server) <
                        noiseVal * generationParams.VoronoiSitePlacementProbability)
                    {
                        sites.Add(new Vector2(x, y));
                    }
                }
            }

            Voronoi          voronoi    = new Voronoi(0.5f);
            List <GraphEdge> edges      = voronoi.MakeVoronoiGraph(sites, size, size);
            float            zoneRadius = size / 2 / generationParams.DifficultyZones;

            sites.Clear();
            foreach (GraphEdge edge in edges)
            {
                if (edge.Point1 == edge.Point2)
                {
                    continue;
                }

                if (Vector2.DistanceSquared(edge.Point1, mapCenter) >= locationRadius * locationRadius ||
                    Vector2.DistanceSquared(edge.Point2, mapCenter) >= locationRadius * locationRadius)
                {
                    continue;
                }

                Location[] newLocations = new Location[2];
                newLocations[0] = Locations.Find(l => l.MapPosition == edge.Point1 || l.MapPosition == edge.Point2);
                newLocations[1] = Locations.Find(l => l != newLocations[0] && (l.MapPosition == edge.Point1 || l.MapPosition == edge.Point2));

                for (int i = 0; i < 2; i++)
                {
                    if (newLocations[i] != null)
                    {
                        continue;
                    }

                    Vector2[] points = new Vector2[] { edge.Point1, edge.Point2 };

                    int positionIndex = Rand.Int(1, Rand.RandSync.Server);

                    Vector2 position = points[positionIndex];
                    if (newLocations[1 - i] != null && newLocations[1 - i].MapPosition == position)
                    {
                        position = points[1 - positionIndex];
                    }
                    int zone = MathHelper.Clamp(generationParams.DifficultyZones - (int)Math.Floor(Vector2.Distance(position, mapCenter) / zoneRadius), 1, generationParams.DifficultyZones);
                    newLocations[i] = Location.CreateRandom(position, zone, Rand.GetRNG(Rand.RandSync.Server));
                    Locations.Add(newLocations[i]);
                }

                var   newConnection = new LocationConnection(newLocations[0], newLocations[1]);
                float centerDist    = Vector2.Distance(newConnection.CenterPos, mapCenter);
                newConnection.Difficulty = MathHelper.Clamp(((1.0f - centerDist / mapRadius) * 100) + Rand.Range(-10.0f, 10.0f, Rand.RandSync.Server), 0, 100);

                connections.Add(newConnection);
            }

            //remove connections that are too short
            float minConnectionDistanceSqr = generationParams.MinConnectionDistance * generationParams.MinConnectionDistance;

            for (int i = connections.Count - 1; i >= 0; i--)
            {
                LocationConnection connection = connections[i];

                if (Vector2.DistanceSquared(connection.Locations[0].MapPosition, connection.Locations[1].MapPosition) > minConnectionDistanceSqr)
                {
                    continue;
                }

                //locations.Remove(connection.Locations[0]);
                connections.Remove(connection);

                foreach (LocationConnection connection2 in connections)
                {
                    if (connection2.Locations[0] == connection.Locations[0])
                    {
                        connection2.Locations[0] = connection.Locations[1];
                    }
                    if (connection2.Locations[1] == connection.Locations[0])
                    {
                        connection2.Locations[1] = connection.Locations[1];
                    }
                }
            }

            HashSet <Location> connectedLocations = new HashSet <Location>();

            foreach (LocationConnection connection in connections)
            {
                connection.Locations[0].Connections.Add(connection);
                connection.Locations[1].Connections.Add(connection);

                connectedLocations.Add(connection.Locations[0]);
                connectedLocations.Add(connection.Locations[1]);
            }

            //remove orphans
            Locations.RemoveAll(c => !connectedLocations.Contains(c));

            //remove locations that are too close to each other
            float minLocationDistanceSqr = generationParams.MinLocationDistance * generationParams.MinLocationDistance;

            for (int i = Locations.Count - 1; i >= 0; i--)
            {
                for (int j = Locations.Count - 1; j > i; j--)
                {
                    float dist = Vector2.DistanceSquared(Locations[i].MapPosition, Locations[j].MapPosition);
                    if (dist > minLocationDistanceSqr)
                    {
                        continue;
                    }
                    //move connections from Locations[j] to Locations[i]
                    foreach (LocationConnection connection in Locations[j].Connections)
                    {
                        if (connection.Locations[0] == Locations[j])
                        {
                            connection.Locations[0] = Locations[i];
                        }
                        else
                        {
                            connection.Locations[1] = Locations[i];
                        }
                        Locations[i].Connections.Add(connection);
                    }
                    Locations.RemoveAt(j);
                }
            }

            for (int i = connections.Count - 1; i >= 0; i--)
            {
                i = Math.Min(i, connections.Count - 1);
                LocationConnection connection = connections[i];
                for (int n = Math.Min(i - 1, connections.Count - 1); n >= 0; n--)
                {
                    if (connection.Locations.Contains(connections[n].Locations[0]) &&
                        connection.Locations.Contains(connections[n].Locations[1]))
                    {
                        connections.RemoveAt(n);
                    }
                }
            }

            foreach (LocationConnection connection in connections)
            {
                float centerDist = Vector2.Distance(connection.CenterPos, mapCenter);
                connection.Difficulty = MathHelper.Clamp(((1.0f - centerDist / mapRadius) * 100) + Rand.Range(-10.0f, 10.0f, Rand.RandSync.Server), 0, 100);
            }

            AssignBiomes();

            GenerateNoiseMapProjSpecific();
        }
Ejemplo n.º 17
0
        private void DrawConnection(SpriteBatch spriteBatch, LocationConnection connection, Rectangle viewArea, Vector2 viewOffset, Color?overrideColor = null)
        {
            Color connectionColor;

            if (GameMain.DebugDraw)
            {
                float sizeFactor = MathUtils.InverseLerp(
                    generationParams.SmallLevelConnectionLength,
                    generationParams.LargeLevelConnectionLength,
                    connection.Length);
                connectionColor = ToolBox.GradientLerp(sizeFactor, Color.LightGreen, GUI.Style.Orange, GUI.Style.Red);
            }
            else if (overrideColor.HasValue)
            {
                connectionColor = overrideColor.Value;
            }
            else
            {
                connectionColor = connection.Passed ? generationParams.ConnectionColor : generationParams.UnvisitedConnectionColor;
            }

            int width = (int)(generationParams.LocationConnectionWidth * zoom);

            if (Level.Loaded?.LevelData == connection.LevelData)
            {
                connectionColor = generationParams.HighlightedConnectionColor;
                width           = (int)(width * 1.5f);
            }
            if (SelectedLocation != CurrentDisplayLocation &&
                (connection.Locations.Contains(SelectedLocation) && connection.Locations.Contains(CurrentDisplayLocation)))
            {
                connectionColor = generationParams.HighlightedConnectionColor;
                width          *= 2;
            }
            else if (HighlightedLocation != CurrentDisplayLocation &&
                     (connection.Locations.Contains(HighlightedLocation) && connection.Locations.Contains(CurrentDisplayLocation)))
            {
                connectionColor = generationParams.HighlightedConnectionColor;
                width          *= 2;
            }

            Vector2 rectCenter = viewArea.Center.ToVector2();

            int startIndex = connection.CrackSegments.Count > 2 ? 1 : 0;
            int endIndex   = connection.CrackSegments.Count > 2 ? connection.CrackSegments.Count - 1 : connection.CrackSegments.Count;

            for (int i = startIndex; i < endIndex; i++)
            {
                var segment = connection.CrackSegments[i];

                Vector2 start = rectCenter + (segment[0] + viewOffset) * zoom;
                Vector2 end   = rectCenter + (segment[1] + viewOffset) * zoom;

                if (!viewArea.Contains(start) && !viewArea.Contains(end))
                {
                    continue;
                }
                else
                {
                    if (MathUtils.GetLineRectangleIntersection(start, end, new Rectangle(viewArea.X, viewArea.Y + viewArea.Height, viewArea.Width, viewArea.Height), out Vector2 intersection))
                    {
                        if (!viewArea.Contains(start))
                        {
                            start = intersection;
                        }
                        else
                        {
                            end = intersection;
                        }
                    }
                }

                float a = 1.0f;
                if (!connection.Locations[0].Discovered && !connection.Locations[1].Discovered)
                {
                    if (IsInFogOfWar(connection.Locations[0]))
                    {
                        a = (float)i / connection.CrackSegments.Count;
                    }
                    else if (IsInFogOfWar(connection.Locations[1]))
                    {
                        a = 1.0f - (float)i / connection.CrackSegments.Count;
                    }
                }
                float dist             = Vector2.Distance(start, end);
                var   connectionSprite = connection.Passed ? generationParams.PassedConnectionSprite : generationParams.ConnectionSprite;
                spriteBatch.Draw(connectionSprite.Texture,
                                 new Rectangle((int)start.X, (int)start.Y, (int)(dist - 1 * zoom), width),
                                 connectionSprite.SourceRect, connectionColor * a, MathUtils.VectorToAngle(end - start),
                                 new Vector2(0, connectionSprite.size.Y / 2), SpriteEffects.None, 0.01f);
            }

            if (GameMain.DebugDraw && zoom > 1.0f && generationParams.ShowLevelTypeNames)
            {
                Vector2 center = rectCenter + (connection.CenterPos + viewOffset) * zoom;
                if (viewArea.Contains(center) && connection.Biome != null)
                {
                    GUI.DrawString(spriteBatch, center, connection.Biome.Identifier + " (" + connection.Difficulty + ")", Color.White);
                }
            }
        }
Ejemplo n.º 18
0
        private void DrawConnection(SpriteBatch spriteBatch, LocationConnection connection, Rectangle viewArea, Vector2 viewOffset, Color?overrideColor = null)
        {
            Color connectionColor;

            if (GameMain.DebugDraw)
            {
                float sizeFactor = MathUtils.InverseLerp(
                    generationParams.SmallLevelConnectionLength,
                    generationParams.LargeLevelConnectionLength,
                    connection.Length);
                connectionColor = ToolBox.GradientLerp(sizeFactor, Color.LightGreen, GUI.Style.Orange, GUI.Style.Red);
            }
            else if (overrideColor.HasValue)
            {
                connectionColor = overrideColor.Value;
            }
            else
            {
                connectionColor = connection.Passed ? generationParams.ConnectionColor : generationParams.UnvisitedConnectionColor;
            }

            int width = (int)(generationParams.LocationConnectionWidth * zoom);

            if (Level.Loaded?.LevelData == connection.LevelData)
            {
                connectionColor = generationParams.HighlightedConnectionColor;
                width           = (int)(width * 1.5f);
            }
            if (SelectedLocation != CurrentDisplayLocation &&
                (connection.Locations.Contains(SelectedLocation) && connection.Locations.Contains(CurrentDisplayLocation)))
            {
                connectionColor = generationParams.HighlightedConnectionColor;
                width          *= 2;
            }
            else if (HighlightedLocation != CurrentDisplayLocation &&
                     (connection.Locations.Contains(HighlightedLocation) && connection.Locations.Contains(CurrentDisplayLocation)))
            {
                connectionColor = generationParams.HighlightedConnectionColor;
                width          *= 2;
            }

            Vector2 rectCenter = viewArea.Center.ToVector2();

            int startIndex = connection.CrackSegments.Count > 2 ? 1 : 0;
            int endIndex   = connection.CrackSegments.Count > 2 ? connection.CrackSegments.Count - 1 : connection.CrackSegments.Count;

            Vector2?connectionStart = null;
            Vector2?connectionEnd   = null;

            for (int i = startIndex; i < endIndex; i++)
            {
                var segment = connection.CrackSegments[i];

                Vector2 start = rectCenter + (segment[0] + viewOffset) * zoom;
                if (!connectionStart.HasValue)
                {
                    connectionStart = start;
                }
                Vector2 end = rectCenter + (segment[1] + viewOffset) * zoom;
                connectionEnd = end;

                if (!viewArea.Contains(start) && !viewArea.Contains(end))
                {
                    continue;
                }
                else
                {
                    if (MathUtils.GetLineRectangleIntersection(start, end, new Rectangle(viewArea.X, viewArea.Y + viewArea.Height, viewArea.Width, viewArea.Height), out Vector2 intersection))
                    {
                        if (!viewArea.Contains(start))
                        {
                            start = intersection;
                        }
                        else
                        {
                            end = intersection;
                        }
                    }
                }

                float a = 1.0f;
                if (!connection.Locations[0].Discovered && !connection.Locations[1].Discovered)
                {
                    if (IsInFogOfWar(connection.Locations[0]))
                    {
                        a = (float)i / connection.CrackSegments.Count;
                    }
                    else if (IsInFogOfWar(connection.Locations[1]))
                    {
                        a = 1.0f - (float)i / connection.CrackSegments.Count;
                    }
                }
                float dist             = Vector2.Distance(start, end);
                var   connectionSprite = connection.Passed ? generationParams.PassedConnectionSprite : generationParams.ConnectionSprite;
                spriteBatch.Draw(connectionSprite.Texture,
                                 new Rectangle((int)start.X, (int)start.Y, (int)(dist - 1 * zoom), width),
                                 connectionSprite.SourceRect, connectionColor * a, MathUtils.VectorToAngle(end - start),
                                 new Vector2(0, connectionSprite.size.Y / 2), SpriteEffects.None, 0.01f);
            }
            if (connectionStart.HasValue && connectionEnd.HasValue)
            {
                GUIComponentStyle crushDepthWarningIconStyle = null;
                string            tooltip = null;
                var subCrushDepth         = Submarine.MainSub?.RealWorldCrushDepth ?? Level.DefaultRealWorldCrushDepth;
                if (GameMain.GameSession?.Campaign?.UpgradeManager != null)
                {
                    var hullUpgradePrefab = UpgradePrefab.Find("increasewallhealth");
                    if (hullUpgradePrefab != null)
                    {
                        int pendingLevel = GameMain.GameSession.Campaign.UpgradeManager.GetUpgradeLevel(hullUpgradePrefab, hullUpgradePrefab.UpgradeCategories.First());
                        int currentLevel = GameMain.GameSession.Campaign.UpgradeManager.GetRealUpgradeLevel(hullUpgradePrefab, hullUpgradePrefab.UpgradeCategories.First());
                        if (pendingLevel > currentLevel)
                        {
                            string updateValueStr = hullUpgradePrefab.SourceElement?.Element("Structure")?.GetAttributeString("crushdepth", null);
                            if (!string.IsNullOrEmpty(updateValueStr))
                            {
                                subCrushDepth = PropertyReference.CalculateUpgrade(subCrushDepth, pendingLevel - currentLevel, updateValueStr);
                            }
                        }
                    }
                }

                if (connection.LevelData.InitialDepth * Physics.DisplayToRealWorldRatio > subCrushDepth)
                {
                    crushDepthWarningIconStyle = GUI.Style.GetComponentStyle("CrushDepthWarningHighIcon");
                    tooltip = "crushdepthwarninghigh";
                }
                else if ((connection.LevelData.InitialDepth + connection.LevelData.Size.Y) * Physics.DisplayToRealWorldRatio > subCrushDepth)
                {
                    crushDepthWarningIconStyle = GUI.Style.GetComponentStyle("CrushDepthWarningLowIcon");
                    tooltip = "crushdepthwarninglow";
                }

                if (crushDepthWarningIconStyle != null)
                {
                    Vector2 iconPos  = (connectionStart.Value + connectionEnd.Value) / 2;
                    float   iconSize = 32.0f * GUI.Scale;
                    bool    mouseOn  = HighlightedLocation == null && Vector2.DistanceSquared(iconPos, PlayerInput.MousePosition) < iconSize * iconSize;
                    Sprite  crushDepthWarningIcon = crushDepthWarningIconStyle.GetDefaultSprite();
                    crushDepthWarningIcon.Draw(spriteBatch, iconPos,
                                               mouseOn ? crushDepthWarningIconStyle.HoverColor : crushDepthWarningIconStyle.Color,
                                               scale: iconSize / crushDepthWarningIcon.size.X);
                    if (mouseOn)
                    {
                        connectionTooltip = new Pair <Rectangle, string>(
                            new Rectangle(iconPos.ToPoint(), new Point((int)iconSize)),
                            TextManager.Get(tooltip)
                            .Replace("[initialdepth]", ((int)(connection.LevelData.InitialDepth * Physics.DisplayToRealWorldRatio)).ToString())
                            .Replace("[submarinecrushdepth]", ((int)subCrushDepth).ToString()));
                    }
                }
            }

            if (GameMain.DebugDraw && zoom > 1.0f && generationParams.ShowLevelTypeNames)
            {
                Vector2 center = rectCenter + (connection.CenterPos + viewOffset) * zoom;
                if (viewArea.Contains(center) && connection.Biome != null)
                {
                    GUI.DrawString(spriteBatch, center, connection.Biome.Identifier + " (" + connection.Difficulty + ")", Color.White);
                }
            }
        }
Ejemplo n.º 19
0
        private void GenerateLocations()
        {
            Voronoi voronoi = new Voronoi(0.5f);

            List <Vector2> sites = new List <Vector2>();

            for (int i = 0; i < 100; i++)
            {
                sites.Add(new Vector2(Rand.Range(0.0f, size, Rand.RandSync.Server), Rand.Range(0.0f, size, Rand.RandSync.Server)));
            }

            List <GraphEdge> edges = voronoi.MakeVoronoiGraph(sites, size, size);

            sites.Clear();
            foreach (GraphEdge edge in edges)
            {
                if (edge.point1 == edge.point2)
                {
                    continue;
                }

                //remove points from the edge of the map
                if (edge.point1.X == 0 || edge.point1.X == size)
                {
                    continue;
                }
                if (edge.point1.Y == 0 || edge.point1.Y == size)
                {
                    continue;
                }
                if (edge.point2.X == 0 || edge.point2.X == size)
                {
                    continue;
                }
                if (edge.point2.Y == 0 || edge.point2.Y == size)
                {
                    continue;
                }

                Location[] newLocations = new Location[2];
                newLocations[0] = locations.Find(l => l.MapPosition == edge.point1 || l.MapPosition == edge.point2);
                newLocations[1] = locations.Find(l => l != newLocations[0] && (l.MapPosition == edge.point1 || l.MapPosition == edge.point2));

                for (int i = 0; i < 2; i++)
                {
                    if (newLocations[i] != null)
                    {
                        continue;
                    }

                    Vector2[] points = new Vector2[] { edge.point1, edge.point2 };

                    int positionIndex = Rand.Int(1, Rand.RandSync.Server);

                    Vector2 position = points[positionIndex];
                    if (newLocations[1 - i] != null && newLocations[1 - i].MapPosition == position)
                    {
                        position = points[1 - positionIndex];
                    }

                    newLocations[i] = Location.CreateRandom(position);
                    locations.Add(newLocations[i]);
                }
                //int seed = (newLocations[0].GetHashCode() | newLocations[1].GetHashCode());
                connections.Add(new LocationConnection(newLocations[0], newLocations[1]));
            }

            //remove connections that are too short
            float minDistance = 50.0f;

            for (int i = connections.Count - 1; i >= 0; i--)
            {
                LocationConnection connection = connections[i];

                if (Vector2.Distance(connection.Locations[0].MapPosition, connection.Locations[1].MapPosition) > minDistance)
                {
                    continue;
                }

                locations.Remove(connection.Locations[0]);
                connections.Remove(connection);

                foreach (LocationConnection connection2 in connections)
                {
                    if (connection2.Locations[0] == connection.Locations[0])
                    {
                        connection2.Locations[0] = connection.Locations[1];
                    }
                    if (connection2.Locations[1] == connection.Locations[0])
                    {
                        connection2.Locations[1] = connection.Locations[1];
                    }
                }
            }

            foreach (LocationConnection connection in connections)
            {
                connection.Locations[0].Connections.Add(connection);
                connection.Locations[1].Connections.Add(connection);
            }

            for (int i = connections.Count - 1; i >= 0; i--)
            {
                i = Math.Min(i, connections.Count - 1);

                LocationConnection connection = connections[i];

                for (int n = Math.Min(i - 1, connections.Count - 1); n >= 0; n--)
                {
                    if (connection.Locations.Contains(connections[n].Locations[0]) &&
                        connection.Locations.Contains(connections[n].Locations[1]))
                    {
                        connections.RemoveAt(n);
                    }
                }
            }


            foreach (LocationConnection connection in connections)
            {
                Vector2 start       = connection.Locations[0].MapPosition;
                Vector2 end         = connection.Locations[1].MapPosition;
                int     generations = (int)(Math.Sqrt(Vector2.Distance(start, end) / 10.0f));
                connection.CrackSegments = MathUtils.GenerateJaggedLine(start, end, generations, 5.0f);
            }

            AssignBiomes();
        }
        private void GenerateConnections()
        {
            foreach (GraphEdge edge in graphEdges)
            {
                if (edge.point1 == edge.point2 || edge.isInternal)
                {
                    continue;
                }

                Location[] newLocations = new Location[2];
                newLocations[0] = locations.Find(l => l.MapPosition == edge.point1 || l.MapPosition == edge.point2);
                newLocations[1] = locations.Find(l => l != newLocations[0] && (l.MapPosition == edge.point1 || l.MapPosition == edge.point2));

                for (int i = 0; i < 2; i++)
                {
                    if (newLocations[i] != null)
                    {
                        continue;
                    }

                    Vector2[] points = new Vector2[] { edge.point1, edge.point2 };

                    int positionIndex = Rand.Int(1, false);

                    Vector2 position = points[positionIndex];
                    if (newLocations[1 - i] != null && newLocations[1 - i].MapPosition == position)
                    {
                        position = points[1 - positionIndex];
                    }

                    newLocations[i] = Location.CreateRandom(position);

                    // DEBUG
                    //newLocations[i].Discovered = true;

                    locations.Add(newLocations[i]);
                }
                LocationConnection newConnection = ConnectLocations(newLocations[0], newLocations[1]);
                newConnection.primaryNodes[0] = edge.node1;
                newConnection.primaryNodes[1] = edge.node2;
                newConnection.secondaryNodes  = edge.secondaryNodes.ToArray();

                /*if (!edge.isInternal && edge.node1 != null && edge.node2 != null && edge.cell1 != null && edge.cell2 != null)
                 * {
                 *  Location newLocation1;
                 *  Location newLocation2;
                 *
                 *  newLocation1 = Location.CreateRandom(edge.node1.mapPosition);
                 *  newLocation2 = Location.CreateRandom(edge.node2.mapPosition);
                 *
                 *  if (!locations.Any(l => l.MapPosition == edge.node1.mapPosition))
                 *      locations.Add(newLocation1);
                 *  else
                 *      newLocation2 = locations.Find(l => l.MapPosition == edge.node1.mapPosition);
                 *  if (!locations.Any(l => l.MapPosition == edge.node2.mapPosition))
                 *      locations.Add(newLocation2);
                 *  else
                 *      newLocation2 = locations.Find(l => l.MapPosition == edge.node2.mapPosition);
                 *
                 *  ConnectLocations(newLocation1, newLocation2);
                 * }*/
            }
            foreach (SecondaryNode node in secondaryNodes)
            {
                if (!node.isOnEdge)
                {
                    Location nodeLocation = Location.CreateRandom(node.mapPosition);
                    locations.Add(nodeLocation);
                    foreach (SecondaryNode subNode in node.attachedNodes)
                    {
                        LocationConnection newConnection = ConnectLocations(nodeLocation, Location.CreateRandom(subNode.mapPosition));
                        subNode.connections.Add(newConnection);
                    }
                }
            }
        }
Ejemplo n.º 21
0
        public static Level CreateRandom(LocationConnection locationConnection)
        {
            string seed = locationConnection.Locations[0].Name + locationConnection.Locations[1].Name;

            return(new Level(seed, locationConnection.Difficulty, LevelGenerationParams.GetRandom(seed, locationConnection.Biome)));
        }
Ejemplo n.º 22
0
        //static because we may need to instantiate the campaign if it hasn't been done yet
        public static void ClientRead(IReadMessage msg)
        {
            bool   isFirstRound         = msg.ReadBoolean();
            byte   campaignID           = msg.ReadByte();
            UInt16 updateID             = msg.ReadUInt16();
            UInt16 saveID               = msg.ReadUInt16();
            string mapSeed              = msg.ReadString();
            UInt16 currentLocIndex      = msg.ReadUInt16();
            UInt16 selectedLocIndex     = msg.ReadUInt16();
            byte   selectedMissionIndex = msg.ReadByte();
            bool   allowDebugTeleport   = msg.ReadBoolean();
            float? reputation           = null;

            if (msg.ReadBoolean())
            {
                reputation = msg.ReadSingle();
            }

            Dictionary <string, float> factionReps = new Dictionary <string, float>();
            byte factionsCount = msg.ReadByte();

            for (int i = 0; i < factionsCount; i++)
            {
                factionReps.Add(msg.ReadString(), msg.ReadSingle());
            }

            bool forceMapUI = msg.ReadBoolean();

            int  money = msg.ReadInt32();
            bool purchasedHullRepairs  = msg.ReadBoolean();
            bool purchasedItemRepairs  = msg.ReadBoolean();
            bool purchasedLostShuttles = msg.ReadBoolean();

            byte missionCount = msg.ReadByte();
            List <Pair <string, byte> > availableMissions = new List <Pair <string, byte> >();

            for (int i = 0; i < missionCount; i++)
            {
                string missionIdentifier = msg.ReadString();
                byte   connectionIndex   = msg.ReadByte();
                availableMissions.Add(new Pair <string, byte>(missionIdentifier, connectionIndex));
            }

            UInt16?storeBalance = null;

            if (msg.ReadBoolean())
            {
                storeBalance = msg.ReadUInt16();
            }

            UInt16 buyCrateItemCount           = msg.ReadUInt16();
            List <PurchasedItem> buyCrateItems = new List <PurchasedItem>();

            for (int i = 0; i < buyCrateItemCount; i++)
            {
                string itemPrefabIdentifier = msg.ReadString();
                int    itemQuantity         = msg.ReadRangedInteger(0, CargoManager.MaxQuantity);
                buyCrateItems.Add(new PurchasedItem(ItemPrefab.Prefabs[itemPrefabIdentifier], itemQuantity));
            }

            UInt16 purchasedItemCount           = msg.ReadUInt16();
            List <PurchasedItem> purchasedItems = new List <PurchasedItem>();

            for (int i = 0; i < purchasedItemCount; i++)
            {
                string itemPrefabIdentifier = msg.ReadString();
                int    itemQuantity         = msg.ReadRangedInteger(0, CargoManager.MaxQuantity);
                purchasedItems.Add(new PurchasedItem(ItemPrefab.Prefabs[itemPrefabIdentifier], itemQuantity));
            }

            UInt16          soldItemCount = msg.ReadUInt16();
            List <SoldItem> soldItems     = new List <SoldItem>();

            for (int i = 0; i < soldItemCount; i++)
            {
                string itemPrefabIdentifier = msg.ReadString();
                UInt16 id       = msg.ReadUInt16();
                bool   removed  = msg.ReadBoolean();
                byte   sellerId = msg.ReadByte();
                soldItems.Add(new SoldItem(ItemPrefab.Prefabs[itemPrefabIdentifier], id, removed, sellerId));
            }

            ushort pendingUpgradeCount = msg.ReadUInt16();
            List <PurchasedUpgrade> pendingUpgrades = new List <PurchasedUpgrade>();

            for (int i = 0; i < pendingUpgradeCount; i++)
            {
                string          upgradeIdentifier  = msg.ReadString();
                UpgradePrefab   prefab             = UpgradePrefab.Find(upgradeIdentifier);
                string          categoryIdentifier = msg.ReadString();
                UpgradeCategory category           = UpgradeCategory.Find(categoryIdentifier);
                int             upgradeLevel       = msg.ReadByte();
                if (prefab == null || category == null)
                {
                    continue;
                }
                pendingUpgrades.Add(new PurchasedUpgrade(prefab, category, upgradeLevel));
            }

            bool          hasCharacterData = msg.ReadBoolean();
            CharacterInfo myCharacterInfo  = null;

            if (hasCharacterData)
            {
                myCharacterInfo = CharacterInfo.ClientRead(CharacterPrefab.HumanSpeciesName, msg);
            }

            if (!(GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign) || campaignID != campaign.CampaignID)
            {
                string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer);

                GameMain.GameSession = new GameSession(null, savePath, GameModePreset.MultiPlayerCampaign, mapSeed);
                campaign             = (MultiPlayerCampaign)GameMain.GameSession.GameMode;
                campaign.CampaignID  = campaignID;
                GameMain.NetLobbyScreen.ToggleCampaignMode(true);
            }

            //server has a newer save file
            if (NetIdUtils.IdMoreRecent(saveID, campaign.PendingSaveID))
            {
                campaign.PendingSaveID = saveID;
            }

            if (NetIdUtils.IdMoreRecent(updateID, campaign.lastUpdateID))
            {
                campaign.SuppressStateSending = true;
                campaign.IsFirstRound         = isFirstRound;

                //we need to have the latest save file to display location/mission/store
                if (campaign.LastSaveID == saveID)
                {
                    campaign.ForceMapUI = forceMapUI;

                    UpgradeStore.WaitForServerUpdate = false;

                    campaign.Map.SetLocation(currentLocIndex == UInt16.MaxValue ? -1 : currentLocIndex);
                    campaign.Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
                    campaign.Map.SelectMission(selectedMissionIndex);
                    campaign.Map.AllowDebugTeleport = allowDebugTeleport;
                    campaign.CargoManager.SetItemsInBuyCrate(buyCrateItems);
                    campaign.CargoManager.SetPurchasedItems(purchasedItems);
                    campaign.CargoManager.SetSoldItems(soldItems);
                    if (storeBalance.HasValue)
                    {
                        campaign.Map.CurrentLocation.StoreCurrentBalance = storeBalance.Value;
                    }
                    campaign.UpgradeManager.SetPendingUpgrades(pendingUpgrades);
                    campaign.UpgradeManager.PurchasedUpgrades.Clear();

                    foreach (var(identifier, rep) in factionReps)
                    {
                        Faction faction = campaign.Factions.FirstOrDefault(f => f.Prefab.Identifier.Equals(identifier, StringComparison.OrdinalIgnoreCase));
                        if (faction?.Reputation != null)
                        {
                            faction.Reputation.Value = rep;
                        }
                        else
                        {
                            DebugConsole.ThrowError($"Received an update for a faction that doesn't exist \"{identifier}\".");
                        }
                    }

                    if (reputation.HasValue)
                    {
                        campaign.Map.CurrentLocation.Reputation.Value = reputation.Value;
                        campaign?.CampaignUI?.UpgradeStore?.RefreshAll();
                    }

                    foreach (var availableMission in availableMissions)
                    {
                        MissionPrefab missionPrefab = MissionPrefab.List.Find(mp => mp.Identifier == availableMission.First);
                        if (missionPrefab == null)
                        {
                            DebugConsole.ThrowError($"Error when receiving campaign data from the server: mission prefab \"{availableMission.First}\" not found.");
                            continue;
                        }
                        if (availableMission.Second < 0 || availableMission.Second >= campaign.Map.CurrentLocation.Connections.Count)
                        {
                            DebugConsole.ThrowError($"Error when receiving campaign data from the server: connection index for mission \"{availableMission.First}\" out of range (index: {availableMission.Second}, current location: {campaign.Map.CurrentLocation.Name}, connections: {campaign.Map.CurrentLocation.Connections.Count}).");
                            continue;
                        }
                        LocationConnection connection = campaign.Map.CurrentLocation.Connections[availableMission.Second];
                        campaign.Map.CurrentLocation.UnlockMission(missionPrefab, connection);
                    }

                    GameMain.NetLobbyScreen.ToggleCampaignMode(true);
                }

                bool shouldRefresh = campaign.Money != money ||
                                     campaign.PurchasedHullRepairs != purchasedHullRepairs ||
                                     campaign.PurchasedItemRepairs != purchasedItemRepairs ||
                                     campaign.PurchasedLostShuttles != purchasedLostShuttles;

                campaign.Money = money;
                campaign.PurchasedHullRepairs  = purchasedHullRepairs;
                campaign.PurchasedItemRepairs  = purchasedItemRepairs;
                campaign.PurchasedLostShuttles = purchasedLostShuttles;

                if (shouldRefresh)
                {
                    campaign?.CampaignUI?.UpgradeStore?.RefreshAll();
                }

                if (myCharacterInfo != null)
                {
                    GameMain.Client.CharacterInfo = myCharacterInfo;
                    GameMain.NetLobbyScreen.SetCampaignCharacterInfo(myCharacterInfo);
                }
                else
                {
                    GameMain.NetLobbyScreen.SetCampaignCharacterInfo(null);
                }

                campaign.lastUpdateID         = updateID;
                campaign.SuppressStateSending = false;
            }
        }
Ejemplo n.º 23
0
        public void ServerWrite(IWriteMessage msg, Client c)
        {
            System.Diagnostics.Debug.Assert(map.Locations.Count < UInt16.MaxValue);

            Reputation reputation = Map?.CurrentLocation?.Reputation;

            msg.Write(IsFirstRound);
            msg.Write(CampaignID);
            msg.Write(lastUpdateID);
            msg.Write(lastSaveID);
            msg.Write(map.Seed);
            msg.Write(map.CurrentLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.CurrentLocationIndex);
            msg.Write(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex);

            var selectedMissionIndices = map.GetSelectedMissionIndices();

            msg.Write((byte)selectedMissionIndices.Count());
            foreach (int selectedMissionIndex in selectedMissionIndices)
            {
                msg.Write((byte)selectedMissionIndex);
            }

            msg.Write(map.AllowDebugTeleport);
            msg.Write(reputation != null);
            if (reputation != null)
            {
                msg.Write(reputation.Value);
            }

            // hopefully we'll never have more than 128 factions
            msg.Write((byte)Factions.Count);
            foreach (Faction faction in Factions)
            {
                msg.Write(faction.Prefab.Identifier);
                msg.Write(faction.Reputation.Value);
            }

            msg.Write(ForceMapUI);

            msg.Write(Money);
            msg.Write(PurchasedHullRepairs);
            msg.Write(PurchasedItemRepairs);
            msg.Write(PurchasedLostShuttles);

            if (map.CurrentLocation != null)
            {
                msg.Write((byte)map.CurrentLocation?.AvailableMissions.Count());
                foreach (Mission mission in map.CurrentLocation.AvailableMissions)
                {
                    msg.Write(mission.Prefab.Identifier);
                    if (mission.Locations[0] == mission.Locations[1])
                    {
                        msg.Write((byte)255);
                    }
                    else
                    {
                        Location           missionDestination = mission.Locations[0] == map.CurrentLocation ? mission.Locations[1] : mission.Locations[0];
                        LocationConnection connection         = map.CurrentLocation.Connections.Find(c => c.OtherLocation(map.CurrentLocation) == missionDestination);
                        msg.Write((byte)map.CurrentLocation.Connections.IndexOf(connection));
                    }
                }

                // Store balance
                msg.Write(true);
                msg.Write((UInt16)map.CurrentLocation.StoreCurrentBalance);
            }
            else
            {
                msg.Write((byte)0);
                // Store balance
                msg.Write(false);
            }

            msg.Write((UInt16)CargoManager.ItemsInBuyCrate.Count);
            foreach (PurchasedItem pi in CargoManager.ItemsInBuyCrate)
            {
                msg.Write(pi.ItemPrefab.Identifier);
                msg.WriteRangedInteger(pi.Quantity, 0, 100);
            }

            msg.Write((UInt16)CargoManager.PurchasedItems.Count);
            foreach (PurchasedItem pi in CargoManager.PurchasedItems)
            {
                msg.Write(pi.ItemPrefab.Identifier);
                msg.WriteRangedInteger(pi.Quantity, 0, 100);
            }

            msg.Write((UInt16)CargoManager.SoldItems.Count);
            foreach (SoldItem si in CargoManager.SoldItems)
            {
                msg.Write(si.ItemPrefab.Identifier);
                msg.Write((UInt16)si.ID);
                msg.Write(si.Removed);
                msg.Write(si.SellerID);
            }

            msg.Write((ushort)UpgradeManager.PendingUpgrades.Count);
            foreach (var(prefab, category, level) in UpgradeManager.PendingUpgrades)
            {
                msg.Write(prefab.Identifier);
                msg.Write(category.Identifier);
                msg.Write((byte)level);
            }

            msg.Write((ushort)UpgradeManager.PurchasedItemSwaps.Count);
            foreach (var itemSwap in UpgradeManager.PurchasedItemSwaps)
            {
                msg.Write(itemSwap.ItemToRemove.ID);
                msg.Write(itemSwap.ItemToInstall?.Identifier ?? string.Empty);
            }

            var characterData = GetClientCharacterData(c);

            if (characterData?.CharacterInfo == null)
            {
                msg.Write(false);
            }
            else
            {
                msg.Write(true);
                characterData.CharacterInfo.ServerWrite(msg);
            }
        }
Ejemplo n.º 24
0
 public void SelectLocation(Location location, LocationConnection locationConnection)
 {
 }
Ejemplo n.º 25
0
        /// <summary>
        /// Load a previously saved campaign map from XML
        /// </summary>
        private Map(CampaignMode campaign, XElement element) : this()
        {
            Seed = element.GetAttributeString("seed", "a");
            Rand.SetSyncedSeed(ToolBox.StringToInt(Seed));
            foreach (XElement subElement in element.Elements())
            {
                switch (subElement.Name.ToString().ToLowerInvariant())
                {
                case "location":
                    int i = subElement.GetAttributeInt("i", 0);
                    while (Locations.Count <= i)
                    {
                        Locations.Add(null);
                    }
                    Locations[i] = new Location(subElement);
                    break;
                }
            }
            System.Diagnostics.Debug.Assert(!Locations.Contains(null));
            for (int i = 0; i < Locations.Count; i++)
            {
                Locations[i].Reputation ??= new Reputation(campaign.CampaignMetadata, $"location.{i}", -100, 100, Rand.Range(-10, 10, Rand.RandSync.Server));
            }

            foreach (XElement subElement in element.Elements())
            {
                switch (subElement.Name.ToString().ToLowerInvariant())
                {
                case "connection":
                    Point locationIndices = subElement.GetAttributePoint("locations", new Point(0, 1));
                    if (locationIndices.X == locationIndices.Y)
                    {
                        continue;
                    }
                    var connection = new LocationConnection(Locations[locationIndices.X], Locations[locationIndices.Y])
                    {
                        Passed     = subElement.GetAttributeBool("passed", false),
                        Difficulty = subElement.GetAttributeFloat("difficulty", 0.0f)
                    };
                    Locations[locationIndices.X].Connections.Add(connection);
                    Locations[locationIndices.Y].Connections.Add(connection);
                    connection.LevelData = new LevelData(subElement.Element("Level"));
                    string biomeId = subElement.GetAttributeString("biome", "");
                    connection.Biome =
                        LevelGenerationParams.GetBiomes().FirstOrDefault(b => b.Identifier == biomeId) ??
                        LevelGenerationParams.GetBiomes().FirstOrDefault(b => b.OldIdentifier == biomeId) ??
                        LevelGenerationParams.GetBiomes().First();
                    Connections.Add(connection);
                    break;
                }
            }

            int startLocationindex = element.GetAttributeInt("startlocation", -1);

            if (startLocationindex > 0 && startLocationindex < Locations.Count)
            {
                StartLocation = Locations[startLocationindex];
            }
            else
            {
                DebugConsole.AddWarning($"Error while loading the map. Start location index out of bounds (index: {startLocationindex}, location count: {Locations.Count}).");
                foreach (Location location in Locations)
                {
                    if (!location.Type.HasOutpost)
                    {
                        continue;
                    }
                    if (StartLocation == null || location.MapPosition.X < StartLocation.MapPosition.X)
                    {
                        StartLocation = location;
                    }
                }
            }
            int endLocationindex = element.GetAttributeInt("endlocation", -1);

            if (endLocationindex > 0 && endLocationindex < Locations.Count)
            {
                EndLocation = Locations[endLocationindex];
            }
            else
            {
                DebugConsole.AddWarning($"Error while loading the map. End location index out of bounds (index: {endLocationindex}, location count: {Locations.Count}).");
                foreach (Location location in Locations)
                {
                    if (EndLocation == null || location.MapPosition.X > EndLocation.MapPosition.X)
                    {
                        EndLocation = location;
                    }
                }
            }

            InitProjectSpecific();
        }
Ejemplo n.º 26
0
        private void CreateEndLocation()
        {
            float   zoneWidth   = Width / generationParams.DifficultyZones;
            Vector2 endPos      = new Vector2(Width - zoneWidth / 2, Height / 2);
            float   closestDist = float.MaxValue;

            EndLocation = Locations.First();
            foreach (Location location in Locations)
            {
                float dist = Vector2.DistanceSquared(endPos, location.MapPosition);
                if (location.Biome.IsEndBiome && dist < closestDist)
                {
                    EndLocation = location;
                    closestDist = dist;
                }
            }

            Location previousToEndLocation = null;

            foreach (Location location in Locations)
            {
                if (!location.Biome.IsEndBiome && (previousToEndLocation == null || location.MapPosition.X > previousToEndLocation.MapPosition.X))
                {
                    previousToEndLocation = location;
                }
            }

            if (EndLocation == null || previousToEndLocation == null)
            {
                return;
            }

            //remove all locations from the end biome except the end location
            for (int i = Locations.Count - 1; i >= 0; i--)
            {
                if (Locations[i].Biome.IsEndBiome && Locations[i] != EndLocation)
                {
                    for (int j = Locations[i].Connections.Count - 1; j >= 0; j--)
                    {
                        if (j >= Locations[i].Connections.Count)
                        {
                            continue;
                        }
                        var connection    = Locations[i].Connections[j];
                        var otherLocation = connection.OtherLocation(Locations[i]);
                        Locations[i].Connections.RemoveAt(j);
                        otherLocation?.Connections.Remove(connection);
                        Connections.Remove(connection);
                    }
                    Locations.RemoveAt(i);
                }
            }

            //removed all connections from the second-to-last location, need to reconnect it
            if (!previousToEndLocation.Connections.Any())
            {
                Location connectTo = Locations.First();
                foreach (Location location in Locations)
                {
                    if (!location.Biome.IsEndBiome && location != previousToEndLocation && location.MapPosition.X > connectTo.MapPosition.X)
                    {
                        connectTo = location;
                    }
                }
                var newConnection = new LocationConnection(previousToEndLocation, connectTo)
                {
                    Biome      = EndLocation.Biome,
                    Difficulty = 100.0f
                };
                Connections.Add(newConnection);
                previousToEndLocation.Connections.Add(newConnection);
                connectTo.Connections.Add(newConnection);
            }

            var endConnection = new LocationConnection(previousToEndLocation, EndLocation)
            {
                Biome      = EndLocation.Biome,
                Difficulty = 100.0f
            };

            Connections.Add(endConnection);
            previousToEndLocation.Connections.Add(endConnection);
            EndLocation.Connections.Add(endConnection);
        }
Ejemplo n.º 27
0
        private void Generate()
        {
            Connections.Clear();
            Locations.Clear();

            List <Vector2> voronoiSites = new List <Vector2>();

            for (float x = 10.0f; x < Width - 10.0f; x += generationParams.VoronoiSiteInterval.X)
            {
                for (float y = 10.0f; y < Height - 10.0f; y += generationParams.VoronoiSiteInterval.Y)
                {
                    voronoiSites.Add(new Vector2(
                                         x + generationParams.VoronoiSiteVariance.X * Rand.Range(-0.5f, 0.5f, Rand.RandSync.Server),
                                         y + generationParams.VoronoiSiteVariance.Y * Rand.Range(-0.5f, 0.5f, Rand.RandSync.Server)));
                }
            }

            Voronoi          voronoi   = new Voronoi(0.5f);
            List <GraphEdge> edges     = voronoi.MakeVoronoiGraph(voronoiSites, Width, Height);
            float            zoneWidth = Width / generationParams.DifficultyZones;

            Vector2 margin = new Vector2(
                Math.Min(10, Width * 0.1f),
                Math.Min(10, Height * 0.2f));

            float startX = margin.X, endX = Width - margin.X;
            float startY = margin.Y, endY = Height - margin.Y;

            if (!edges.Any())
            {
                throw new Exception($"Generating a campaign map failed (no edges in the voronoi graph). Width: {Width}, height: {Height}, margin: {margin}");
            }

            voronoiSites.Clear();
            foreach (GraphEdge edge in edges)
            {
                if (edge.Point1 == edge.Point2)
                {
                    continue;
                }

                if (edge.Point1.X < margin.X || edge.Point1.X > Width - margin.X || edge.Point1.Y < startY || edge.Point1.Y > endY)
                {
                    continue;
                }
                if (edge.Point2.X < margin.X || edge.Point2.X > Width - margin.X || edge.Point2.Y < startY || edge.Point2.Y > endY)
                {
                    continue;
                }

                Location[] newLocations = new Location[2];
                newLocations[0] = Locations.Find(l => l.MapPosition == edge.Point1 || l.MapPosition == edge.Point2);
                newLocations[1] = Locations.Find(l => l != newLocations[0] && (l.MapPosition == edge.Point1 || l.MapPosition == edge.Point2));

                for (int i = 0; i < 2; i++)
                {
                    if (newLocations[i] != null)
                    {
                        continue;
                    }

                    Vector2[] points = new Vector2[] { edge.Point1, edge.Point2 };

                    int positionIndex = Rand.Int(1, Rand.RandSync.Server);

                    Vector2 position = points[positionIndex];
                    if (newLocations[1 - i] != null && newLocations[1 - i].MapPosition == position)
                    {
                        position = points[1 - positionIndex];
                    }
                    int zone = MathHelper.Clamp((int)Math.Floor(position.X / zoneWidth) + 1, 1, generationParams.DifficultyZones);
                    newLocations[i] = Location.CreateRandom(position, zone, Rand.GetRNG(Rand.RandSync.Server), requireOutpost: false, Locations);
                    Locations.Add(newLocations[i]);
                }

                var newConnection = new LocationConnection(newLocations[0], newLocations[1]);
                Connections.Add(newConnection);
            }

            //remove connections that are too short
            float minConnectionDistanceSqr = generationParams.MinConnectionDistance * generationParams.MinConnectionDistance;

            for (int i = Connections.Count - 1; i >= 0; i--)
            {
                LocationConnection connection = Connections[i];

                if (Vector2.DistanceSquared(connection.Locations[0].MapPosition, connection.Locations[1].MapPosition) > minConnectionDistanceSqr)
                {
                    continue;
                }

                //locations.Remove(connection.Locations[0]);
                Connections.Remove(connection);

                foreach (LocationConnection connection2 in Connections)
                {
                    if (connection2.Locations[0] == connection.Locations[0])
                    {
                        connection2.Locations[0] = connection.Locations[1];
                    }
                    if (connection2.Locations[1] == connection.Locations[0])
                    {
                        connection2.Locations[1] = connection.Locations[1];
                    }
                }
            }

            HashSet <Location> connectedLocations = new HashSet <Location>();

            foreach (LocationConnection connection in Connections)
            {
                connection.Locations[0].Connections.Add(connection);
                connection.Locations[1].Connections.Add(connection);

                connectedLocations.Add(connection.Locations[0]);
                connectedLocations.Add(connection.Locations[1]);
            }

            //remove orphans
            Locations.RemoveAll(c => !connectedLocations.Contains(c));

            //remove locations that are too close to each other
            float minLocationDistanceSqr = generationParams.MinLocationDistance * generationParams.MinLocationDistance;

            for (int i = Locations.Count - 1; i >= 0; i--)
            {
                for (int j = Locations.Count - 1; j > i; j--)
                {
                    float dist = Vector2.DistanceSquared(Locations[i].MapPosition, Locations[j].MapPosition);
                    if (dist > minLocationDistanceSqr)
                    {
                        continue;
                    }
                    //move connections from Locations[j] to Locations[i]
                    foreach (LocationConnection connection in Locations[j].Connections)
                    {
                        if (connection.Locations[0] == Locations[j])
                        {
                            connection.Locations[0] = Locations[i];
                        }
                        else
                        {
                            connection.Locations[1] = Locations[i];
                        }

                        if (connection.Locations[0] != connection.Locations[1])
                        {
                            Locations[i].Connections.Add(connection);
                        }
                        else
                        {
                            Connections.Remove(connection);
                        }
                    }
                    Locations[i].Connections.RemoveAll(c => c.OtherLocation(Locations[i]) == Locations[j]);
                    Locations.RemoveAt(j);
                }
            }

            for (int i = Connections.Count - 1; i >= 0; i--)
            {
                i = Math.Min(i, Connections.Count - 1);
                LocationConnection connection = Connections[i];
                for (int n = Math.Min(i - 1, Connections.Count - 1); n >= 0; n--)
                {
                    if (connection.Locations.Contains(Connections[n].Locations[0]) &&
                        connection.Locations.Contains(Connections[n].Locations[1]))
                    {
                        Connections.RemoveAt(n);
                    }
                }
            }

            foreach (Location location in Locations)
            {
                for (int i = location.Connections.Count - 1; i >= 0; i--)
                {
                    if (!Connections.Contains(location.Connections[i]))
                    {
                        location.Connections.RemoveAt(i);
                    }
                }
            }

            foreach (LocationConnection connection in Connections)
            {
                connection.Difficulty = MathHelper.Clamp((connection.CenterPos.X / Width * 100) + Rand.Range(-10.0f, 0.0f, Rand.RandSync.Server), 1.2f, 100.0f);
            }

            AssignBiomes();
            CreateEndLocation();

            foreach (Location location in Locations)
            {
                location.LevelData = new LevelData(location);
            }
            foreach (LocationConnection connection in Connections)
            {
                connection.LevelData = new LevelData(connection);
            }
        }
Ejemplo n.º 28
0
        public void SelectLocation(Location location, LocationConnection connection)
        {
            selectedLocationInfo.ClearChildren();
            missionPanel.Visible = location != null;

            if (location == null)
            {
                return;
            }

            var container = selectedLocationInfo;

            new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), container.RectTransform), location.Name, font: GUI.LargeFont)
            {
                AutoScale = true
            };
            new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), container.RectTransform), location.Type.Name);

            Sprite portrait = location.Type.GetPortrait(location.PortraitId);

            new GUIImage(new RectTransform(new Vector2(1.0f, 0.6f),
                                           container.RectTransform), portrait, scaleToFit: true);

            new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), container.RectTransform), TextManager.Get("SelectMission"), font: GUI.LargeFont)
            {
                AutoScale = true
            };

            var missionFrame   = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.3f), container.RectTransform), style: "InnerFrame");
            var missionContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), missionFrame.RectTransform, Anchor.Center))
            {
                RelativeSpacing = 0.02f,
                Stretch         = true
            };

            SelectedLevel = connection?.Level;
            if (connection != null)
            {
                Point          maxTickBoxSize    = new Point(int.MaxValue, missionContent.Rect.Height / 4);
                List <Mission> availableMissions = Campaign.Map.CurrentLocation.GetMissionsInConnection(connection).ToList();
                if (!availableMissions.Contains(null))
                {
                    availableMissions.Add(null);
                }

                Mission selectedMission = Campaign.Map.CurrentLocation.SelectedMission != null && availableMissions.Contains(Campaign.Map.CurrentLocation.SelectedMission) ?
                                          Campaign.Map.CurrentLocation.SelectedMission : null;
                missionTickBoxes.Clear();
                foreach (Mission mission in availableMissions)
                {
                    var tickBox = new GUITickBox(new RectTransform(new Vector2(0.1f, 0.1f), missionContent.RectTransform)
                    {
                        MaxSize = maxTickBoxSize
                    },
                                                 mission?.Name ?? TextManager.Get("NoMission"))
                    {
                        UserData   = mission,
                        Enabled    = GameMain.Client == null || GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign),
                        Selected   = mission == selectedMission,
                        OnSelected = (tb) =>
                        {
                            if (!tb.Selected)
                            {
                                return(false);
                            }
                            RefreshMissionTab(tb.UserData as Mission);
                            Campaign.Map.OnMissionSelected?.Invoke(connection, mission);
                            if ((Campaign is MultiPlayerCampaign multiPlayerCampaign) && !multiPlayerCampaign.SuppressStateSending &&
                                GameMain.Client != null && GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign))
                            {
                                GameMain.Client?.SendCampaignState();
                            }
                            return(true);
                        }
                    };
                    missionTickBoxes.Add(tickBox);
                }

                RefreshMissionTab(selectedMission);

                StartButton = new GUIButton(new RectTransform(new Vector2(0.3f, 0.7f), missionContent.RectTransform, Anchor.CenterRight),
                                            TextManager.Get("StartCampaignButton"), style: "GUIButtonLarge")
                {
                    IgnoreLayoutGroups = true,
                    OnClicked          = (GUIButton btn, object obj) => { StartRound?.Invoke(); return(true); },
                    Enabled            = true
                };
                if (GameMain.Client != null)
                {
                    StartButton.Visible = !GameMain.Client.GameStarted &&
                                          (GameMain.Client.HasPermission(Networking.ClientPermissions.ManageRound) ||
                                           GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign));
                }
            }

            OnLocationSelected?.Invoke(location, connection);
        }
Ejemplo n.º 29
0
        public void SelectLocation(Location location, LocationConnection connection)
        {
            locationInfoPanel.ClearChildren();
            //don't select the map panel if we're looking at some other tab
            if (selectedTab == CampaignMode.InteractionType.Map)
            {
                SelectTab(CampaignMode.InteractionType.Map);
                locationInfoPanel.Visible = location != null;
            }

            Location prevSelectedLocation  = selectedLocation;
            float    prevMissionListScroll = missionList?.BarScroll ?? 0.0f;

            selectedLocation = location;
            if (location == null)
            {
                return;
            }

            int padding = GUI.IntScale(20);

            var content = new GUILayoutGroup(new RectTransform(locationInfoPanel.Rect.Size - new Point(padding * 2), locationInfoPanel.RectTransform, Anchor.Center), childAnchor: Anchor.TopRight)
            {
                Stretch         = true,
                RelativeSpacing = 0.02f,
            };

            new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), location.Name, font: GUI.LargeFont)
            {
                AutoScaleHorizontal = true
            };
            new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), location.Type.Name, font: GUI.SubHeadingFont);

            Sprite portrait = location.Type.GetPortrait(location.PortraitId);

            portrait.EnsureLazyLoaded();

            var portraitContainer = new GUICustomComponent(new RectTransform(new Vector2(1.0f, 0.3f), content.RectTransform), onDraw: (sb, customComponent) =>
            {
                portrait.Draw(sb, customComponent.Rect.Center.ToVector2(), Color.Gray, portrait.size / 2, scale: Math.Max(customComponent.Rect.Width / portrait.size.X, customComponent.Rect.Height / portrait.size.Y));
            })
            {
                HideElementsOutsideFrame = true
            };

            var textContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), portraitContainer.RectTransform, Anchor.Center))
            {
                RelativeSpacing = 0.05f
            };

            if (connection?.LevelData != null)
            {
                var biomeLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), textContent.RectTransform),
                                                  TextManager.Get("Biome", fallBackTag: "location"), font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft);
                new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), biomeLabel.RectTransform), connection.Biome.DisplayName, textAlignment: Alignment.CenterRight);

                var difficultyLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), textContent.RectTransform),
                                                       TextManager.Get("LevelDifficulty"), font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft);
                new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), difficultyLabel.RectTransform), ((int)connection.LevelData.Difficulty) + " %", textAlignment: Alignment.CenterRight);
            }

            missionList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.4f), content.RectTransform))
            {
                Spacing = (int)(5 * GUI.yScale)
            };

            SelectedLevel = connection?.LevelData;
            Location currentDisplayLocation = Campaign.CurrentDisplayLocation;

            if (connection != null && connection.Locations.Contains(currentDisplayLocation))
            {
                List <Mission> availableMissions = currentDisplayLocation.GetMissionsInConnection(connection).ToList();
                if (!availableMissions.Contains(null))
                {
                    availableMissions.Insert(0, null);
                }

                Mission selectedMission = currentDisplayLocation.SelectedMission != null && availableMissions.Contains(currentDisplayLocation.SelectedMission) ?
                                          currentDisplayLocation.SelectedMission : null;

                missionList.Content.ClearChildren();

                foreach (Mission mission in availableMissions)
                {
                    var missionPanel = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), missionList.Content.RectTransform), style: null)
                    {
                        UserData = mission
                    };
                    var missionTextContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), missionPanel.RectTransform, Anchor.Center))
                    {
                        Stretch      = true,
                        CanBeFocused = true
                    };

                    var missionName = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), mission?.Name ?? TextManager.Get("NoMission"), font: GUI.SubHeadingFont, wrap: true);
                    if (mission != null)
                    {
                        if (MapGenerationParams.Instance?.MissionIcon != null)
                        {
                            var icon = new GUIImage(new RectTransform(Vector2.One * 0.9f, missionName.RectTransform, anchor: Anchor.CenterLeft, scaleBasis: ScaleBasis.Smallest)
                            {
                                AbsoluteOffset = new Point((int)missionName.Padding.X, 0)
                            },
                                                    MapGenerationParams.Instance.MissionIcon, scaleToFit: true)
                            {
                                Color         = MapGenerationParams.Instance.IndicatorColor * 0.5f,
                                SelectedColor = MapGenerationParams.Instance.IndicatorColor,
                                HoverColor    = Color.Lerp(MapGenerationParams.Instance.IndicatorColor, Color.White, 0.5f)
                            };
                            missionName.Padding = new Vector4(missionName.Padding.X + icon.Rect.Width * 1.5f, missionName.Padding.Y, missionName.Padding.Z, missionName.Padding.W);
                        }
                        new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform),
                                         TextManager.GetWithVariable("missionreward", "[reward]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", mission.Reward)), wrap: true);
                        new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), mission.Description, wrap: true);
                    }
                    missionPanel.RectTransform.MinSize = new Point(0, (int)(missionTextContent.Children.Sum(c => c.Rect.Height) / missionTextContent.RectTransform.RelativeSize.Y) + GUI.IntScale(20));
                    foreach (GUIComponent child in missionTextContent.Children)
                    {
                        var textBlock = child as GUITextBlock;
                        textBlock.Color          = textBlock.SelectedColor = textBlock.HoverColor = Color.Transparent;
                        textBlock.HoverTextColor = textBlock.TextColor;
                        textBlock.TextColor     *= 0.5f;
                    }
                    missionPanel.OnAddedToGUIUpdateList = (c) =>
                    {
                        missionTextContent.Children.ForEach(child => child.State = c.State);
                    };

                    if (mission != availableMissions.Last())
                    {
                        new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), missionList.Content.RectTransform), style: "HorizontalLine")
                        {
                            CanBeFocused = false
                        };
                    }
                }
                missionList.Select(selectedMission);
                if (prevSelectedLocation == selectedLocation)
                {
                    missionList.BarScroll = prevMissionListScroll;
                }

                if (Campaign.AllowedToManageCampaign())
                {
                    missionList.OnSelected = (component, userdata) =>
                    {
                        Mission mission = userdata as Mission;
                        if (Campaign.Map.CurrentLocation.SelectedMission == mission)
                        {
                            return(false);
                        }
                        Campaign.Map.CurrentLocation.SelectedMission = mission;
                        //RefreshMissionInfo(mission);
                        if ((Campaign is MultiPlayerCampaign multiPlayerCampaign) && !multiPlayerCampaign.SuppressStateSending &&
                            Campaign.AllowedToManageCampaign())
                        {
                            GameMain.Client?.SendCampaignState();
                        }
                        return(true);
                    };
                }
            }

            StartButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.1f), content.RectTransform),
                                        TextManager.Get("StartCampaignButton"), style: "GUIButtonLarge")
            {
                OnClicked = (GUIButton btn, object obj) => { StartRound?.Invoke(); return(true); },
                Enabled   = true,
                Visible   = Campaign.AllowedToEndRound()
            };

            if (Level.Loaded != null &&
                connection.LevelData == Level.Loaded.LevelData &&
                currentDisplayLocation == Campaign.Map?.CurrentLocation)
            {
                StartButton.Visible = false;
                missionList.Enabled = false;
            }
        }