public override void Update(float deltaTime)
        {
            if (isFinished)
            {
                return;
            }

            if (GameMain.GameSession?.EventManager != null)
            {
                var eventPrefab = EventSet.GetEventPrefab(Identifier);
                if (eventPrefab == null)
                {
                    DebugConsole.ThrowError($"Error in TriggerEventAction - could not find an event with the identifier {Identifier}.");
                }
                else
                {
                    var ev = eventPrefab.CreateInstance();
                    if (ev != null)
                    {
                        GameMain.GameSession.EventManager.QueuedEvents.Enqueue(ev);
                    }
                }
            }

            isFinished = true;
        }
Example #2
0
        private bool CanStartEventSet(EventSet eventSet)
        {
            ISpatialEntity refEntity     = GetRefEntity();
            float          distFromStart = Vector2.Distance(refEntity.WorldPosition, level.StartPosition);
            float          distFromEnd   = Vector2.Distance(refEntity.WorldPosition, level.EndPosition);

            //don't create new events if within 50 meters of the start/end of the level
            if (!eventSet.AllowAtStart)
            {
                if (distanceTraveled <= 0.0f ||
                    distFromStart * Physics.DisplayToRealWorldRatio < 50.0f ||
                    distFromEnd * Physics.DisplayToRealWorldRatio < 50.0f)
                {
                    return(false);
                }
            }

            if ((Submarine.MainSub == null || distanceTraveled < eventSet.MinDistanceTraveled) &&
                roundDuration < eventSet.MinMissionTime)
            {
                return(false);
            }

            if (CurrentIntensity < eventSet.MinIntensity || CurrentIntensity > eventSet.MaxIntensity)
            {
                return(false);
            }

            return(true);
        }
Example #3
0
 static void CheckEventSet(EventDebugStats stats, EventSet thisSet)
 {
     if (thisSet.ChooseRandom)
     {
         var unusedEvents = thisSet.EventPrefabs.ToList();
         for (int i = 0; i < thisSet.EventCount; i++)
         {
             var eventPrefab = ToolBox.SelectWeightedRandom(unusedEvents, unusedEvents.Select(e => e.Commonness).ToList(), Rand.RandSync.Unsynced);
             if (eventPrefab.Prefabs.Any(p => p != null))
             {
                 AddEvents(stats, eventPrefab.Prefabs);
                 unusedEvents.Remove(eventPrefab);
             }
         }
     }
     else
     {
         foreach (var eventPrefab in thisSet.EventPrefabs)
         {
             AddEvents(stats, eventPrefab.Prefabs);
         }
     }
     foreach (var childSet in thisSet.ChildSets)
     {
         CheckEventSet(stats, childSet);
     }
 }
Example #4
0
 static void CheckEventSet(EventDebugStats stats, EventSet thisSet)
 {
     if (thisSet.ChooseRandom)
     {
         List <Pair <EventPrefab, float> > unusedEvents = new List <Pair <EventPrefab, float> >(thisSet.EventPrefabs);
         for (int i = 0; i < thisSet.EventCount; i++)
         {
             var eventPrefab = ToolBox.SelectWeightedRandom(unusedEvents, unusedEvents.Select(e => e.Second).ToList(), Rand.RandSync.Unsynced);
             if (eventPrefab != null)
             {
                 AddEvent(stats, eventPrefab.First);
                 unusedEvents.Remove(eventPrefab);
             }
         }
     }
     else
     {
         foreach (var eventPrefab in thisSet.EventPrefabs)
         {
             AddEvent(stats, eventPrefab.First);
         }
     }
     foreach (var childSet in thisSet.ChildSets)
     {
         CheckEventSet(stats, childSet);
     }
 }
Example #5
0
        /// <summary>
        /// Triggers the event immediately, ignoring any delays
        /// </summary>
        private void TriggerEvent(MissionPrefab.TriggerEvent trigger)
        {
            if (trigger.CampaignOnly && GameMain.GameSession?.Campaign == null)
            {
                return;
            }
            var eventPrefab = EventSet.GetAllEventPrefabs().Find(p => p.Identifier.Equals(trigger.EventIdentifier, StringComparison.OrdinalIgnoreCase));

            if (eventPrefab == null)
            {
                DebugConsole.ThrowError($"Mission \"{Name}\" failed to trigger an event (couldn't find an event with the identifier \"{trigger.EventIdentifier}\").");
                return;
            }
            if (GameMain.GameSession?.EventManager != null)
            {
                var newEvent = eventPrefab.CreateInstance();
                GameMain.GameSession.EventManager.ActiveEvents.Add(newEvent);
                newEvent.Init(true);
            }
        }
Example #6
0
        public void Init()
        {
            NPCSet.LoadSets();
            FactionPrefab.LoadFactions();
            CharacterPrefab.LoadAll();
            MissionPrefab.Init();
            TraitorMissionPrefab.Init();
            MapEntityPrefab.Init();
            MapGenerationParams.Init();
            LevelGenerationParams.LoadPresets();
            CaveGenerationParams.LoadPresets();
            OutpostGenerationParams.LoadPresets();
            EventSet.LoadPrefabs();
            Order.Init();
            EventManagerSettings.Init();
            ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item));
            AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions));
            SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings));
            StructurePrefab.LoadAll(GetFilesOfType(ContentType.Structure));
            UpgradePrefab.LoadAll(GetFilesOfType(ContentType.UpgradeModules));
            JobPrefab.LoadAll(GetFilesOfType(ContentType.Jobs));
            CorpsePrefab.LoadAll(GetFilesOfType(ContentType.Corpses));
            NPCConversation.LoadAll(GetFilesOfType(ContentType.NPCConversations));
            ItemAssemblyPrefab.LoadAll();
            LevelObjectPrefab.LoadAll();
            BallastFloraPrefab.LoadAll(GetFilesOfType(ContentType.MapCreature));
            TalentPrefab.LoadAll(GetFilesOfType(ContentType.Talents));
            TalentTree.LoadAll(GetFilesOfType(ContentType.TalentTrees));

            GameModePreset.Init();
            DecalManager = new DecalManager();
            LocationType.Init();

            SubmarineInfo.RefreshSavedSubs();

            Screen.SelectNull();

            NetLobbyScreen = new NetLobbyScreen();

            CheckContentPackage();
        }
Example #7
0
        private bool CanStartEventSet(EventSet eventSet)
        {
            ISpatialEntity refEntity     = GetRefEntity();
            float          distFromStart = (float)Math.Sqrt(MathUtils.LineSegmentToPointDistanceSquared(level.StartExitPosition.ToPoint(), level.StartPosition.ToPoint(), refEntity.WorldPosition.ToPoint()));
            float          distFromEnd   = (float)Math.Sqrt(MathUtils.LineSegmentToPointDistanceSquared(level.EndExitPosition.ToPoint(), level.EndPosition.ToPoint(), refEntity.WorldPosition.ToPoint()));

            //don't create new events if within 50 meters of the start/end of the level
            if (!eventSet.AllowAtStart)
            {
                if (distanceTraveled <= 0.0f ||
                    distFromStart * Physics.DisplayToRealWorldRatio < 50.0f ||
                    distFromEnd * Physics.DisplayToRealWorldRatio < 50.0f)
                {
                    return(false);
                }
            }

            if (eventSet.DelayWhenCrewAway)
            {
                if ((isCrewAway && crewAwayDuration < settings.FreezeDurationWhenCrewAway) || crewAwayResetTimer > 0.0f)
                {
                    return(false);
                }
            }

            if ((Submarine.MainSub == null || distanceTraveled < eventSet.MinDistanceTraveled) &&
                roundDuration < eventSet.MinMissionTime)
            {
                return(false);
            }

            if (CurrentIntensity < eventSet.MinIntensity || CurrentIntensity > eventSet.MaxIntensity)
            {
                return(false);
            }

            return(true);
        }
        public static List <string> GetDebugStatistics(int simulatedRoundCount = 100)
        {
            List <string> debugLines = new List <string>();

            foreach (var eventSet in List)
            {
                List <EventDebugStats> stats = new List <EventDebugStats>();
                for (int i = 0; i < simulatedRoundCount; i++)
                {
                    var newStats = new EventDebugStats(eventSet);
                    CheckEventSet(newStats, eventSet);
                    stats.Add(newStats);
                }
                debugLines.Add($"Event stats ({eventSet.DebugIdentifier}): ");
                LogEventStats(stats, debugLines);
            }

            for (int difficulty = 0; difficulty <= 100; difficulty += 10)
            {
                debugLines.Add($"Event stats on difficulty level {difficulty}: ");
                List <EventDebugStats> stats = new List <EventDebugStats>();
                for (int i = 0; i < simulatedRoundCount; i++)
                {
                    EventSet selectedSet = List.Where(s => difficulty >= s.MinLevelDifficulty && difficulty <= s.MaxLevelDifficulty).GetRandom();
                    if (selectedSet == null)
                    {
                        continue;
                    }
                    var newStats = new EventDebugStats(selectedSet);
                    CheckEventSet(newStats, selectedSet);
                    stats.Add(newStats);
                }
                LogEventStats(stats, debugLines);
            }

            return(debugLines);
Example #9
0
        private void CreateEvents(EventSet eventSet)
        {
            if (level == null)
            {
                return;
            }
            int applyCount = 1;

            if (eventSet.PerRuin)
            {
                applyCount = Level.Loaded.Ruins.Count();
            }
            else if (eventSet.PerWreck)
            {
                applyCount = Submarine.Loaded.Count(s => s.Info.IsWreck && (s.WreckAI == null || !s.WreckAI.IsAlive));
            }
            for (int i = 0; i < applyCount; i++)
            {
                if (eventSet.ChooseRandom)
                {
                    if (eventSet.EventPrefabs.Count > 0)
                    {
                        int seed = ToolBox.StringToInt(level.Seed);
                        foreach (var previousEvent in level.LevelData.EventHistory)
                        {
                            seed |= ToolBox.StringToInt(previousEvent.Identifier);
                        }

                        MTRandom rand = new MTRandom(seed);
                        List <Pair <EventPrefab, float> > unusedEvents = new List <Pair <EventPrefab, float> >(eventSet.EventPrefabs);
                        for (int j = 0; j < eventSet.EventCount; j++)
                        {
                            var eventPrefab = ToolBox.SelectWeightedRandom(unusedEvents, unusedEvents.Select(e => CalculateCommonness(e)).ToList(), rand);
                            if (eventPrefab != null)
                            {
                                var newEvent = eventPrefab.First.CreateInstance();
                                newEvent.Init(true);
                                DebugConsole.Log("Initialized event " + newEvent.ToString());
                                if (!selectedEvents.ContainsKey(eventSet))
                                {
                                    selectedEvents.Add(eventSet, new List <Event>());
                                }
                                selectedEvents[eventSet].Add(newEvent);
                                unusedEvents.Remove(eventPrefab);
                            }
                        }
                    }
                    if (eventSet.ChildSets.Count > 0)
                    {
                        var newEventSet = SelectRandomEvents(eventSet.ChildSets);
                        if (newEventSet != null)
                        {
                            CreateEvents(newEventSet);
                        }
                    }
                }
                else
                {
                    foreach (Pair <EventPrefab, float> eventPrefab in eventSet.EventPrefabs)
                    {
                        var newEvent = eventPrefab.First.CreateInstance();
                        newEvent.Init(true);
                        DebugConsole.Log("Initialized event " + newEvent.ToString());
                        if (!selectedEvents.ContainsKey(eventSet))
                        {
                            selectedEvents.Add(eventSet, new List <Event>());
                        }
                        selectedEvents[eventSet].Add(newEvent);
                    }

                    foreach (EventSet childEventSet in eventSet.ChildSets)
                    {
                        CreateEvents(childEventSet);
                    }
                }
            }
        }
 public EventDebugStats(EventSet rootSet)
 {
     RootSet = rootSet;
 }
        private EventSet(XElement element, string debugIdentifier, EventSet parentSet = null)
        {
            DebugIdentifier = element.GetAttributeString("identifier", null) ?? debugIdentifier;
            Commonness      = new Dictionary <string, float>();
            EventPrefabs    = new List <Pair <EventPrefab, float> >();
            ChildSets       = new List <EventSet>();

            MinLevelDifficulty = element.GetAttributeFloat("minleveldifficulty", 0);
            MaxLevelDifficulty = Math.Max(element.GetAttributeFloat("maxleveldifficulty", 100), MinLevelDifficulty);

            string levelTypeStr = element.GetAttributeString("leveltype", "LocationConnection");

            if (!Enum.TryParse(levelTypeStr, true, out LevelType))
            {
                DebugConsole.ThrowError($"Error in event set \"{debugIdentifier}\". \"{levelTypeStr}\" is not a valid level type.");
            }

            string[] locationTypeStr = element.GetAttributeStringArray("locationtype", null);
            if (locationTypeStr != null)
            {
                LocationTypeIdentifiers = locationTypeStr;
                if (LocationType.List.Any())
                {
                    CheckLocationTypeErrors();
                }
            }

            MinIntensity = element.GetAttributeFloat("minintensity", 0.0f);
            MaxIntensity = Math.Max(element.GetAttributeFloat("maxintensity", 100.0f), MinIntensity);

            ChooseRandom        = element.GetAttributeBool("chooserandom", false);
            EventCount          = element.GetAttributeInt("eventcount", 1);
            MinDistanceTraveled = element.GetAttributeFloat("mindistancetraveled", 0.0f);
            MinMissionTime      = element.GetAttributeFloat("minmissiontime", 0.0f);

            AllowAtStart         = element.GetAttributeBool("allowatstart", false);
            PerRuin              = element.GetAttributeBool("perruin", false);
            PerCave              = element.GetAttributeBool("percave", false);
            PerWreck             = element.GetAttributeBool("perwreck", false);
            IgnoreCoolDown       = element.GetAttributeBool("ignorecooldown", parentSet?.IgnoreCoolDown ?? (PerRuin || PerCave || PerWreck));
            DelayWhenCrewAway    = element.GetAttributeBool("delaywhencrewaway", !PerRuin && !PerCave && !PerWreck);
            OncePerOutpost       = element.GetAttributeBool("perwreck", false);
            TriggerEventCooldown = element.GetAttributeBool("triggereventcooldown", true);

            Commonness[""] = 1.0f;
            foreach (XElement subElement in element.Elements())
            {
                switch (subElement.Name.ToString().ToLowerInvariant())
                {
                case "commonness":
                    Commonness[""] = subElement.GetAttributeFloat("commonness", 0.0f);
                    foreach (XElement overrideElement in subElement.Elements())
                    {
                        if (overrideElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase))
                        {
                            string levelType = overrideElement.GetAttributeString("leveltype", "");
                            if (!Commonness.ContainsKey(levelType))
                            {
                                Commonness.Add(levelType, overrideElement.GetAttributeFloat("commonness", 0.0f));
                            }
                        }
                    }
                    break;

                case "eventset":
                    ChildSets.Add(new EventSet(subElement, this.DebugIdentifier + "-" + ChildSets.Count, this));
                    break;

                default:
                    //an element with just an identifier = reference to an event prefab
                    if (!subElement.HasElements && subElement.Attributes().First().Name.ToString().Equals("identifier", StringComparison.OrdinalIgnoreCase))
                    {
                        string identifier = subElement.GetAttributeString("identifier", "");
                        var    prefab     = PrefabList.Find(p => p.Identifier.Equals(identifier, StringComparison.OrdinalIgnoreCase));
                        if (prefab == null)
                        {
                            DebugConsole.ThrowError($"Error in event set \"{debugIdentifier}\" - could not find the event prefab \"{identifier}\".");
                        }
                        else
                        {
                            float commonness = subElement.GetAttributeFloat("commonness", prefab.Commonness);
                            EventPrefabs.Add(new Pair <EventPrefab, float>(prefab, commonness));
                        }
                    }
                    else
                    {
                        var prefab = new EventPrefab(subElement);
                        EventPrefabs.Add(new Pair <EventPrefab, float>(prefab, prefab.Commonness));
                    }
                    break;
                }
            }
        }
Example #12
0
        private void CreateEvents(EventSet eventSet, Random rand)
        {
            if (level == null)
            {
                return;
            }
            if (level.LevelData.HasHuntingGrounds && eventSet.DisableInHuntingGrounds)
            {
                return;
            }
#if DEBUG
            DebugConsole.NewMessage($"Loading event set {eventSet.DebugIdentifier}", Color.LightBlue);
#else
            DebugConsole.Log($"Loading event set {eventSet.DebugIdentifier}");
#endif
            int applyCount = 1;
            List <Func <Level.InterestingPosition, bool> > spawnPosFilter = new List <Func <Level.InterestingPosition, bool> >();
            if (eventSet.PerRuin)
            {
                applyCount = level.Ruins.Count();
                foreach (var ruin in level.Ruins)
                {
                    spawnPosFilter.Add((Level.InterestingPosition pos) => { return(pos.Ruin == ruin); });
                }
            }
            else if (eventSet.PerCave)
            {
                applyCount = level.Caves.Count();
                foreach (var cave in level.Caves)
                {
                    spawnPosFilter.Add((Level.InterestingPosition pos) => { return(pos.Cave == cave); });
                }
            }
            else if (eventSet.PerWreck)
            {
                var wrecks = Submarine.Loaded.Where(s => s.Info.IsWreck && (s.WreckAI == null || !s.WreckAI.IsAlive));
                applyCount = wrecks.Count();
                foreach (var wreck in wrecks)
                {
                    spawnPosFilter.Add((Level.InterestingPosition pos) => { return(pos.Submarine == wreck); });
                }
            }

            bool isPrefabSuitable(EventPrefab p)
            => string.IsNullOrEmpty(p.BiomeIdentifier) ||
            p.BiomeIdentifier.Equals(level.LevelData?.Biome?.Identifier, StringComparison.OrdinalIgnoreCase);

            var suitablePrefabSubsets = eventSet.EventPrefabs
                                        .FindAll(p => p.Prefabs.Any(isPrefabSuitable));

            for (int i = 0; i < applyCount; i++)
            {
                if (eventSet.ChooseRandom)
                {
                    if (suitablePrefabSubsets.Count > 0)
                    {
                        var unusedEvents = suitablePrefabSubsets.ToList();
                        for (int j = 0; j < eventSet.EventCount; j++)
                        {
                            if (unusedEvents.All(e => e.Prefabs.All(p => CalculateCommonness(p, e.Commonness) <= 0.0f)))
                            {
                                break;
                            }
                            EventSet.SubEventPrefab subEventPrefab = ToolBox.SelectWeightedRandom(unusedEvents, unusedEvents.Select(e => e.Prefabs.Max(p => CalculateCommonness(p, e.Commonness))).ToList(), rand);
                            (IEnumerable <EventPrefab> eventPrefabs, float commonness, float probability) = subEventPrefab;
                            if (eventPrefabs != null && rand.NextDouble() <= probability)
                            {
                                var finalPrefabs            = eventPrefabs.Where(isPrefabSuitable).ToArray();
                                var finalPrefabCommonnesses = finalPrefabs.Select(p => p.Commonness).ToArray();
                                var eventPrefab             = ToolBox.SelectWeightedRandom(finalPrefabs, finalPrefabCommonnesses, rand);

                                var newEvent = eventPrefab.CreateInstance();
                                if (newEvent == null)
                                {
                                    continue;
                                }
                                newEvent.Init(true);
                                if (i < spawnPosFilter.Count)
                                {
                                    newEvent.SpawnPosFilter = spawnPosFilter[i];
                                }
#if DEBUG
                                DebugConsole.NewMessage($"Initialized event {newEvent}");
#else
                                DebugConsole.Log($"Initialized event {newEvent}");
#endif
                                if (!selectedEvents.ContainsKey(eventSet))
                                {
                                    selectedEvents.Add(eventSet, new List <Event>());
                                }
                                selectedEvents[eventSet].Add(newEvent);
                                unusedEvents.Remove(subEventPrefab);
                            }
                        }
                    }
                    if (eventSet.ChildSets.Count > 0)
                    {
                        var newEventSet = SelectRandomEvents(eventSet.ChildSets, rand);
                        if (newEventSet != null)
                        {
                            CreateEvents(newEventSet, rand);
                        }
                    }
                }
                else
                {
                    foreach ((IEnumerable <EventPrefab> eventPrefabs, float commonness, float probability) in suitablePrefabSubsets)
                    {
                        if (rand.NextDouble() > probability)
                        {
                            continue;
                        }

                        var finalPrefabs            = eventPrefabs.Where(isPrefabSuitable).ToArray();
                        var finalPrefabCommonnesses = finalPrefabs.Select(p => p.Commonness).ToArray();
                        var eventPrefab             = ToolBox.SelectWeightedRandom(finalPrefabs, finalPrefabCommonnesses, rand);
                        var newEvent = eventPrefab.CreateInstance();
                        if (newEvent == null)
                        {
                            continue;
                        }
                        newEvent.Init(true);
#if DEBUG
                        DebugConsole.NewMessage($"Initialized event {newEvent}");
#else
                        DebugConsole.Log($"Initialized event {newEvent}");
#endif
                        if (!selectedEvents.ContainsKey(eventSet))
                        {
                            selectedEvents.Add(eventSet, new List <Event>());
                        }
                        selectedEvents[eventSet].Add(newEvent);
                    }

                    foreach (EventSet childEventSet in eventSet.ChildSets)
                    {
                        CreateEvents(childEventSet, rand);
                    }
                }
            }
        }
        private static void CreateDialog(string text, Character speaker, IEnumerable <string> options, int[] closingOptions, string spriteIdentifier = null,
                                         ConversationAction actionInstance = null, UInt16?actionId = null, bool fadeToBlack = false, DialogTypes dialogType = DialogTypes.Regular, bool continueConversation = false)
        {
            Debug.Assert(actionInstance == null || actionId == null);

            if (GUI.InputBlockingMenuOpen)
            {
                if (actionId.HasValue)
                {
                    SendIgnore(actionId.Value);
                }
                return;
            }

            shouldFadeToBlack = fadeToBlack;

            if (lastMessageBox != null && !lastMessageBox.Closed && GUIMessageBox.MessageBoxes.Contains(lastMessageBox))
            {
                if (actionId != null && lastMessageBox.UserData is Pair <string, ushort> userData)
                {
                    if (userData.Second == actionId)
                    {
                        return;
                    }
                    lastMessageBox.UserData = new Pair <string, ushort>("ConversationAction", actionId.Value);
                }

                GUIListBox conversationList = lastMessageBox.FindChild("conversationlist", true) as GUIListBox;
                Debug.Assert(conversationList != null);

                // gray out the last text block
                if (conversationList.Content.Children.LastOrDefault() is GUILayoutGroup lastElement)
                {
                    if (lastElement.FindChild("text", true) is GUITextBlock textLayout)
                    {
                        textLayout.OverrideTextColor(Color.DarkGray * 0.8f);
                    }
                }

                List <GUIButton> extraButtons = CreateConversation(conversationList, text, speaker, options, string.IsNullOrWhiteSpace(spriteIdentifier));
                AssignActionsToButtons(extraButtons, lastMessageBox);
                RecalculateLastMessage(conversationList, true);

                conversationList.ScrollToEnd(0.5f);
                lastMessageBox.SetBackgroundIcon(EventSet.GetEventSprite(spriteIdentifier));
                return;
            }

            var(relative, min) = GetSizes(dialogType);

            GUIMessageBox messageBox = new GUIMessageBox(string.Empty, string.Empty, new string[0],
                                                         relativeSize: relative, minSize: min,
                                                         type: GUIMessageBox.Type.InGame, backgroundIcon: EventSet.GetEventSprite(spriteIdentifier))
            {
                UserData = "ConversationAction"
            };

            lastMessageBox = messageBox;

            messageBox.InnerFrame.ClearChildren();
            messageBox.AutoClose = false;
            GUI.Style.Apply(messageBox.InnerFrame, "DialogBox");

            if (actionInstance != null)
            {
                lastActiveAction         = actionInstance;
                actionInstance.dialogBox = messageBox;
            }
            else
            {
                messageBox.UserData = new Pair <string, UInt16>("ConversationAction", actionId.Value);
            }

            int padding = GUI.IntScale(16);

            GUIListBox listBox = new GUIListBox(new RectTransform(messageBox.InnerFrame.Rect.Size - new Point(padding * 2), messageBox.InnerFrame.RectTransform, Anchor.Center), style: null)
            {
                KeepSpaceForScrollBar = true,
                HoverCursor           = CursorState.Default,
                UserData = "conversationlist"
            };

            List <GUIButton> buttons = CreateConversation(listBox, text, speaker, options, string.IsNullOrWhiteSpace(spriteIdentifier));

            AssignActionsToButtons(buttons, messageBox);
            RecalculateLastMessage(listBox, false);

            messageBox.InnerFrame.RectTransform.MinSize = new Point(0, Math.Max(listBox.RectTransform.MinSize.Y + padding * 2, (int)(100 * GUI.yScale)));

            var shadow = new GUIFrame(new RectTransform(messageBox.InnerFrame.Rect.Size + new Point(padding * 4), messageBox.InnerFrame.RectTransform, Anchor.Center), style: "OuterGlow")
            {
                Color = Color.Black * 0.7f
            };

            shadow.SetAsFirstChild();
Example #14
0
        private static void CreateDialog(string text, Character speaker, IEnumerable <string> options, int[] closingOptions, string spriteIdentifier = null,
                                         ConversationAction actionInstance = null, UInt16?actionId = null, bool fadeToBlack = false, DialogTypes dialogType = DialogTypes.Regular, bool continueConversation = false)
        {
            Debug.Assert(actionInstance == null || actionId == null);

            shouldFadeToBlack = fadeToBlack;

            if (lastMessageBox != null && !lastMessageBox.Closed && GUIMessageBox.MessageBoxes.Contains(lastMessageBox))
            {
                if (actionId != null && lastMessageBox.UserData is Pair <string, ushort> userData)
                {
                    if (userData.Second == actionId)
                    {
                        return;
                    }
                    lastMessageBox.UserData = new Pair <string, ushort>("ConversationAction", actionId.Value);
                }

                GUIListBox conversationList = lastMessageBox.FindChild("conversationlist", true) as GUIListBox;
                Debug.Assert(conversationList != null);

                // gray out the last text block
                if (conversationList.Content.Children.LastOrDefault() is GUILayoutGroup lastElement)
                {
                    if (lastElement.FindChild("text", true) is GUITextBlock textLayout)
                    {
                        textLayout.OverrideTextColor(Color.DarkGray * 0.8f);
                    }
                }

                List <GUIButton> extraButtons = CreateConversation(conversationList, text, speaker, options, string.IsNullOrWhiteSpace(spriteIdentifier));
                AssignActionsToButtons(extraButtons, lastMessageBox);
                RecalculateLastMessage(conversationList, true);

                conversationList.ScrollToEnd(0.5f);
                lastMessageBox.SetBackgroundIcon(EventSet.GetEventSprite(spriteIdentifier));
                return;
            }

            var(relative, min) = GetSizes(dialogType);

            GUIMessageBox messageBox = new GUIMessageBox(string.Empty, string.Empty, new string[0],
                                                         relativeSize: relative, minSize: min,
                                                         type: GUIMessageBox.Type.InGame, backgroundIcon: EventSet.GetEventSprite(spriteIdentifier))
            {
                UserData = "ConversationAction"
            };

            lastMessageBox = messageBox;

            messageBox.InnerFrame.ClearChildren();
            messageBox.AutoClose = false;
            GUI.Style.Apply(messageBox.InnerFrame, "DialogBox");

            if (actionInstance != null)
            {
                lastActiveAction         = actionInstance;
                actionInstance.dialogBox = messageBox;
            }
            else
            {
                messageBox.UserData = new Pair <string, UInt16>("ConversationAction", actionId.Value);
            }

            int padding = GUI.IntScale(16);

            GUIListBox listBox = new GUIListBox(new RectTransform(messageBox.InnerFrame.Rect.Size - new Point(padding * 2), messageBox.InnerFrame.RectTransform, Anchor.Center), style: null)
            {
                KeepSpaceForScrollBar = true,
                HoverCursor           = CursorState.Default,
                UserData = "conversationlist"
            };

            List <GUIButton> buttons = CreateConversation(listBox, text, speaker, options, string.IsNullOrWhiteSpace(spriteIdentifier));

            AssignActionsToButtons(buttons, messageBox);
            RecalculateLastMessage(listBox, false);

            messageBox.InnerFrame.RectTransform.MinSize = new Point(0, Math.Max(listBox.RectTransform.MinSize.Y + padding * 2, (int)(100 * GUI.yScale)));

            var shadow = new GUIFrame(new RectTransform(messageBox.InnerFrame.Rect.Size + new Point(padding * 4), messageBox.InnerFrame.RectTransform, Anchor.Center), style: "OuterGlow")
            {
                Color = Color.Black * 0.7f
            };

            shadow.SetAsFirstChild();

            void RecalculateLastMessage(GUIListBox conversationList, bool append)
            {
                if (conversationList.Content.Children.LastOrDefault() is GUILayoutGroup lastElement)
                {
                    GUILayoutGroup textLayout = lastElement.GetChild <GUILayoutGroup>();
                    if (lastElement.Rect.Size.Y < textLayout.Rect.Size.Y && !append)
                    {
                        lastElement.RectTransform.MinSize = textLayout.Rect.Size;
                    }
                    if (textLayout != null)
                    {
                        int textHeight = textLayout.Children.Sum(c => c.Rect.Height);
                        textLayout.RectTransform.MaxSize = new Point(lastElement.RectTransform.MaxSize.X, textHeight);
                        textLayout.Recalculate();
                    }
                    int sumHeight = lastElement.Children.Sum(c => c.Rect.Height);
                    lastElement.RectTransform.MaxSize = new Point(lastElement.RectTransform.MaxSize.X, sumHeight);
                    lastElement.Recalculate();
                    conversationList.RecalculateChildren();

                    if (!append || textLayout == null)
                    {
                        return;
                    }

                    foreach (GUIComponent child in textLayout.Children)
                    {
                        conversationList.UpdateScrollBarSize();
                        float wait = conversationList.BarSize < 1.0f ? 0.5f : 0.0f;

                        if (child is GUITextBlock)
                        {
                            child.FadeIn(wait, 0.5f);
                        }

                        if (child is GUIButton btn)
                        {
                            btn.FadeIn(wait, 1.0f);
                            btn.TextBlock.FadeIn(wait, 0.5f);
                        }
                    }
                }
            }

            void AssignActionsToButtons(List <GUIButton> optionButtons, GUIMessageBox target)
            {
                if (!options.Any())
                {
                    GUIButton closeButton = new GUIButton(new RectTransform(Vector2.One, target.InnerFrame.RectTransform, Anchor.BottomRight, scaleBasis: ScaleBasis.Smallest)
                    {
                        MaxSize        = new Point(GUI.IntScale(24)),
                        MinSize        = new Point(24),
                        AbsoluteOffset = new Point(GUI.IntScale(48), GUI.IntScale(16))
                    }, style: "GUIButtonVerticalArrow")
                    {
                        UserData           = "ContinueButton",
                        IgnoreLayoutGroups = true,
                        Bounce             = true,
                        OnClicked          = (btn, userdata) =>
                        {
                            if (actionInstance != null)
                            {
                                actionInstance.selectedOption = 0;
                            }
                            else if (actionId.HasValue)
                            {
                                SendResponse(actionId.Value, 0);
                            }

                            if (!continueConversation)
                            {
                                target.Close();
                            }
                            else
                            {
                                btn.Frame.FadeOut(0.33f, true);
                            }

                            return(true);
                        }
                    };

                    closeButton.Children.ForEach(child => child.SpriteEffects = SpriteEffects.FlipVertically);
                    closeButton.Frame.FadeIn(0.5f, 0.5f);
                    closeButton.SlideIn(0.5f, 0.33f, 16, SlideDirection.Down);
                }

                for (int i = 0; i < optionButtons.Count; i++)
                {
                    optionButtons[i].UserData   = i;
                    optionButtons[i].OnClicked += (btn, userdata) =>
                    {
                        int selectedOption = (userdata as int?) ?? 0;
                        if (actionInstance != null)
                        {
                            actionInstance.selectedOption = selectedOption;
                            foreach (GUIButton otherButton in optionButtons)
                            {
                                otherButton.CanBeFocused = false;
                                if (otherButton != btn)
                                {
                                    otherButton.TextBlock.OverrideTextColor(Color.DarkGray * 0.8f);
                                }
                            }
                            btn.ExternalHighlight = true;
                            return(true);
                        }

                        if (actionId.HasValue)
                        {
                            SendResponse(actionId.Value, selectedOption);
                            btn.CanBeFocused      = false;
                            btn.ExternalHighlight = true;
                            foreach (GUIButton otherButton in optionButtons)
                            {
                                otherButton.CanBeFocused = false;
                                if (otherButton != btn)
                                {
                                    otherButton.TextBlock.OverrideTextColor(Color.DarkGray * 0.8f);
                                }
                            }
                            return(true);
                        }
                        //should not happen
                        return(false);
                    };

                    if (closingOptions.Contains(i))
                    {
                        optionButtons[i].OnClicked += target.Close;
                    }
                }
            }
        }
Example #15
0
        private IEnumerable <object> Load(bool isSeparateThread)
        {
            if (GameSettings.VerboseLogging)
            {
                DebugConsole.NewMessage("LOADING COROUTINE", Color.Lime);
            }

            while (TitleScreen.WaitForLanguageSelection)
            {
                yield return(CoroutineStatus.Running);
            }

            SoundManager = new Sounds.SoundManager();
            SoundManager.SetCategoryGainMultiplier("default", Config.SoundVolume, 0);
            SoundManager.SetCategoryGainMultiplier("ui", Config.SoundVolume, 0);
            SoundManager.SetCategoryGainMultiplier("waterambience", Config.SoundVolume, 0);
            SoundManager.SetCategoryGainMultiplier("music", Config.MusicVolume, 0);
            SoundManager.SetCategoryGainMultiplier("voip", Math.Min(Config.VoiceChatVolume, 1.0f), 0);

            if (Config.EnableSplashScreen && !ConsoleArguments.Contains("-skipintro"))
            {
                var   pendingSplashScreens = TitleScreen.PendingSplashScreens;
                float baseVolume           = MathHelper.Clamp(Config.SoundVolume * 2.0f, 0.0f, 1.0f);
                pendingSplashScreens?.Enqueue(new LoadingScreen.PendingSplashScreen("Content/SplashScreens/Splash_UTG.webm", baseVolume * 0.5f));
                pendingSplashScreens?.Enqueue(new LoadingScreen.PendingSplashScreen("Content/SplashScreens/Splash_FF.webm", baseVolume));
                pendingSplashScreens?.Enqueue(new LoadingScreen.PendingSplashScreen("Content/SplashScreens/Splash_Daedalic.webm", baseVolume * 0.1f));
            }

            //if not loading in a separate thread, wait for the splash screens to finish before continuing the loading
            //otherwise the videos will look extremely choppy
            if (!isSeparateThread)
            {
                while (TitleScreen.PlayingSplashScreen || TitleScreen.PendingSplashScreens.Count > 0)
                {
                    yield return(CoroutineStatus.Running);
                }
            }

            GUI.Init(Window, Config.AllEnabledPackages, GraphicsDevice);
            DebugConsole.Init();

            if (Config.AutoUpdateWorkshopItems)
            {
                Config.WaitingForAutoUpdate = true;
                TaskPool.Add("AutoUpdateWorkshopItemsAsync",
                             SteamManager.AutoUpdateWorkshopItemsAsync(), (task) =>
                {
                    bool result = ((Task <bool>)task).Result;

                    Config.WaitingForAutoUpdate = false;
                });

                while (Config.WaitingForAutoUpdate)
                {
                    yield return(CoroutineStatus.Running);
                }
            }

#if DEBUG
            if (Config.ModBreakerMode)
            {
                Config.SelectCorePackage(ContentPackage.CorePackages.GetRandom());
                foreach (var regularPackage in ContentPackage.RegularPackages)
                {
                    if (Rand.Range(0.0, 1.0) <= 0.5)
                    {
                        Config.EnableRegularPackage(regularPackage);
                    }
                    else
                    {
                        Config.DisableRegularPackage(regularPackage);
                    }
                }
                ContentPackage.SortContentPackages(p =>
                {
                    return(Rand.Int(int.MaxValue));
                });
            }
#endif

            if (Config.AllEnabledPackages.None())
            {
                DebugConsole.Log("No content packages selected");
            }
            else
            {
                DebugConsole.Log("Selected content packages: " + string.Join(", ", Config.AllEnabledPackages.Select(cp => cp.Name)));
            }

#if DEBUG
            GameSettings.ShowUserStatisticsPrompt = false;
            GameSettings.SendUserStatistics       = false;
#endif

            InitUserStats();

            yield return(CoroutineStatus.Running);

            Debug.WriteLine("sounds");

            int i = 0;
            foreach (object crObj in SoundPlayer.Init())
            {
                CoroutineStatus status = (CoroutineStatus)crObj;
                if (status == CoroutineStatus.Success)
                {
                    break;
                }

                i++;
                TitleScreen.LoadState = SoundPlayer.SoundCount == 0 ?
                                        1.0f :
                                        Math.Min(40.0f * i / Math.Max(SoundPlayer.SoundCount, 1), 40.0f);

                yield return(CoroutineStatus.Running);
            }

            TitleScreen.LoadState = 40.0f;
            yield return(CoroutineStatus.Running);

            LightManager = new Lights.LightManager(base.GraphicsDevice, Content);

            TitleScreen.LoadState = 41.0f;
            yield return(CoroutineStatus.Running);

            GUI.LoadContent();
            TitleScreen.LoadState = 42.0f;

            yield return(CoroutineStatus.Running);

            TaskPool.Add("InitRelayNetworkAccess", SteamManager.InitRelayNetworkAccess(), (t) => { });

            FactionPrefab.LoadFactions();
            NPCSet.LoadSets();
            CharacterPrefab.LoadAll();
            MissionPrefab.Init();
            TraitorMissionPrefab.Init();
            MapEntityPrefab.Init();
            Tutorials.Tutorial.Init();
            MapGenerationParams.Init();
            LevelGenerationParams.LoadPresets();
            CaveGenerationParams.LoadPresets();
            OutpostGenerationParams.LoadPresets();
            WreckAIConfig.LoadAll();
            EventSet.LoadPrefabs();
            ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item));
            AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions));
            SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings));
            Order.Init();
            EventManagerSettings.Init();
            BallastFloraPrefab.LoadAll(GetFilesOfType(ContentType.MapCreature));
            HintManager.Init();
            TitleScreen.LoadState = 50.0f;
            yield return(CoroutineStatus.Running);

            StructurePrefab.LoadAll(GetFilesOfType(ContentType.Structure));
            TitleScreen.LoadState = 55.0f;
            yield return(CoroutineStatus.Running);

            UpgradePrefab.LoadAll(GetFilesOfType(ContentType.UpgradeModules));
            TitleScreen.LoadState = 56.0f;
            yield return(CoroutineStatus.Running);

            JobPrefab.LoadAll(GetFilesOfType(ContentType.Jobs));
            CorpsePrefab.LoadAll(GetFilesOfType(ContentType.Corpses));

            NPCConversation.LoadAll(GetFilesOfType(ContentType.NPCConversations));

            ItemAssemblyPrefab.LoadAll();
            TitleScreen.LoadState = 60.0f;
            yield return(CoroutineStatus.Running);

            GameModePreset.Init();

            SaveUtil.DeleteDownloadedSubs();
            SubmarineInfo.RefreshSavedSubs();

            TitleScreen.LoadState = 65.0f;
            yield return(CoroutineStatus.Running);

            GameScreen = new GameScreen(GraphicsDeviceManager.GraphicsDevice, Content);

            TitleScreen.LoadState = 68.0f;
            yield return(CoroutineStatus.Running);

            MainMenuScreen   = new MainMenuScreen(this);
            ServerListScreen = new ServerListScreen();

            TitleScreen.LoadState = 70.0f;
            yield return(CoroutineStatus.Running);

#if USE_STEAM
            SteamWorkshopScreen = new SteamWorkshopScreen();
            if (SteamManager.IsInitialized)
            {
                Steamworks.SteamFriends.OnGameRichPresenceJoinRequested += OnInvitedToGame;
                Steamworks.SteamFriends.OnGameLobbyJoinRequested        += OnLobbyJoinRequested;
            }
#endif

            SubEditorScreen = new SubEditorScreen();

            TitleScreen.LoadState = 75.0f;
            yield return(CoroutineStatus.Running);

            ParticleEditorScreen = new ParticleEditorScreen();

            TitleScreen.LoadState = 80.0f;
            yield return(CoroutineStatus.Running);

            LevelEditorScreen     = new LevelEditorScreen();
            SpriteEditorScreen    = new SpriteEditorScreen();
            EventEditorScreen     = new EventEditorScreen();
            CharacterEditorScreen = new CharacterEditor.CharacterEditorScreen();
            CampaignEndScreen     = new CampaignEndScreen();

            yield return(CoroutineStatus.Running);

            TitleScreen.LoadState = 85.0f;
            ParticleManager       = new ParticleManager(GameScreen.Cam);
            ParticleManager.LoadPrefabs();
            TitleScreen.LoadState = 88.0f;
            LevelObjectPrefab.LoadAll();

            TitleScreen.LoadState = 90.0f;
            yield return(CoroutineStatus.Running);

            DecalManager = new DecalManager();
            LocationType.Init();
            MainMenuScreen.Select();

            foreach (string steamError in SteamManager.InitializationErrors)
            {
                new GUIMessageBox(TextManager.Get("Error"), TextManager.Get(steamError));
            }

            TitleScreen.LoadState = 100.0f;
            hasLoaded             = true;
            if (GameSettings.VerboseLogging)
            {
                DebugConsole.NewMessage("LOADING COROUTINE FINISHED", Color.Lime);
            }
            yield return(CoroutineStatus.Success);
        }
Example #16
0
        public void StartRound(Level level)
        {
            this.level = level;

            if (isClient)
            {
                return;
            }

            pendingEventSets.Clear();
            selectedEvents.Clear();
            activeEvents.Clear();

            pathFinder      = new PathFinder(WayPoint.WayPointList, false);
            totalPathLength = 0.0f;
            if (level != null)
            {
                var steeringPath = pathFinder.FindPath(ConvertUnits.ToSimUnits(level.StartPosition), ConvertUnits.ToSimUnits(level.EndPosition));
                totalPathLength = steeringPath.TotalLength;
            }

            SelectSettings();

            int seed = 0;

            if (level != null)
            {
                seed = ToolBox.StringToInt(level.Seed);
                foreach (var previousEvent in level.LevelData.EventHistory)
                {
                    seed ^= ToolBox.StringToInt(previousEvent.Identifier);
                }
            }
            MTRandom rand = new MTRandom(seed);

            EventSet initialEventSet = SelectRandomEvents(EventSet.List, rand);
            EventSet additiveSet     = null;

            if (initialEventSet != null && initialEventSet.Additive)
            {
                additiveSet     = initialEventSet;
                initialEventSet = SelectRandomEvents(EventSet.List.FindAll(e => !e.Additive), rand);
            }
            if (initialEventSet != null)
            {
                pendingEventSets.Add(initialEventSet);
                CreateEvents(initialEventSet, rand);
            }
            if (additiveSet != null)
            {
                pendingEventSets.Add(additiveSet);
                CreateEvents(additiveSet, rand);
            }

            if (level?.LevelData?.Type == LevelData.LevelType.Outpost)
            {
                //if the outpost is connected to a locked connection, create an event to unlock it
                if (level.StartLocation?.Connections.Any(c => c.Locked && level.StartLocation.MapPosition.X < c.OtherLocation(level.StartLocation).MapPosition.X) ?? false)
                {
                    var unlockPathPrefabs         = EventSet.PrefabList.FindAll(e => e.UnlockPathEvent);
                    var unlockPathPrefabsForBiome = unlockPathPrefabs.FindAll(e =>
                                                                              string.IsNullOrEmpty(e.BiomeIdentifier) ||
                                                                              e.BiomeIdentifier.Equals(level.LevelData.Biome.Identifier, StringComparison.OrdinalIgnoreCase));

                    var unlockPathEventPrefab = unlockPathPrefabsForBiome.Any() ?
                                                ToolBox.SelectWeightedRandom(unlockPathPrefabsForBiome, unlockPathPrefabsForBiome.Select(b => b.Commonness).ToList(), rand) :
                                                ToolBox.SelectWeightedRandom(unlockPathPrefabs, unlockPathPrefabs.Select(b => b.Commonness).ToList(), rand);
                    if (unlockPathEventPrefab != null)
                    {
                        var newEvent = unlockPathEventPrefab.CreateInstance();
                        newEvent.Init(true);
                        ActiveEvents.Add(newEvent);
                    }
                    else
                    {
                        //if no event that unlocks the path can be found, unlock it automatically
                        level.StartLocation.Connections.ForEach(c => c.Locked = false);
                    }
                }

                level.LevelData.EventHistory.AddRange(selectedEvents.Values.SelectMany(v => v).Select(e => e.Prefab).Where(e => !level.LevelData.EventHistory.Contains(e)));
                if (level.LevelData.EventHistory.Count > MaxEventHistory)
                {
                    level.LevelData.EventHistory.RemoveRange(0, level.LevelData.EventHistory.Count - MaxEventHistory);
                }
                AddChildEvents(initialEventSet);
                void AddChildEvents(EventSet eventSet)
                {
                    if (eventSet == null)
                    {
                        return;
                    }
                    if (eventSet.OncePerOutpost)
                    {
                        foreach (EventPrefab ep in eventSet.EventPrefabs.SelectMany(e => e.Prefabs))
                        {
                            if (!level.LevelData.NonRepeatableEvents.Contains(ep))
                            {
                                level.LevelData.NonRepeatableEvents.Add(ep);
                            }
                        }
                    }
                    foreach (EventSet childSet in eventSet.ChildSets)
                    {
                        AddChildEvents(childSet);
                    }
                }
            }

            PreloadContent(GetFilesToPreload());

            roundDuration        = 0.0f;
            isCrewAway           = false;
            crewAwayDuration     = 0.0f;
            crewAwayResetTimer   = 0.0f;
            intensityUpdateTimer = 0.0f;
            CalculateCurrentIntensity(0.0f);
            currentIntensity = targetIntensity;
            eventCoolDown    = 0.0f;
        }
Example #17
0
        private void CreateGUI()
        {
            GuiFrame = new GUIFrame(new RectTransform(new Vector2(0.2f, 0.4f), GUICanvas.Instance)
            {
                MinSize = new Point(300, 400)
            });
            GUILayoutGroup layoutGroup = new GUILayoutGroup(RectTransform(0.9f, 0.9f, GuiFrame, Anchor.Center))
            {
                Stretch = true
            };

            // === BUTTONS === //
            GUILayoutGroup buttonLayout = new GUILayoutGroup(RectTransform(1.0f, 0.50f, layoutGroup))
            {
                RelativeSpacing = 0.04f
            };
            GUIButton newProjectButton    = new GUIButton(RectTransform(1.0f, 0.33f, buttonLayout), TextManager.Get("EventEditor.NewProject"));
            GUIButton saveProjectButton   = new GUIButton(RectTransform(1.0f, 0.33f, buttonLayout), TextManager.Get("EventEditor.SaveProject"));
            GUIButton loadProjectButton   = new GUIButton(RectTransform(1.0f, 0.33f, buttonLayout), TextManager.Get("EventEditor.LoadProject"));
            GUIButton exportProjectButton = new GUIButton(RectTransform(1.0f, 0.33f, buttonLayout), TextManager.Get("EventEditor.Export"));


            // === LOAD PREFAB === //

            GUILayoutGroup loadEventLayout = new GUILayoutGroup(RectTransform(1.0f, 0.125f, layoutGroup));

            new GUITextBlock(RectTransform(1.0f, 0.5f, loadEventLayout), TextManager.Get("EventEditor.LoadEvent"), font: GUI.SubHeadingFont);

            GUILayoutGroup loadDropdownLayout = new GUILayoutGroup(RectTransform(1.0f, 0.5f, loadEventLayout), isHorizontal: true, childAnchor: Anchor.CenterLeft);
            GUIDropDown    loadDropdown       = new GUIDropDown(RectTransform(0.8f, 1.0f, loadDropdownLayout), elementCount: 10);
            GUIButton      loadButton         = new GUIButton(RectTransform(0.2f, 1.0f, loadDropdownLayout), TextManager.Get("Load"));

            // === ADD ACTION === //

            GUILayoutGroup addActionLayout = new GUILayoutGroup(RectTransform(1.0f, 0.125f, layoutGroup));

            new GUITextBlock(RectTransform(1.0f, 0.5f, addActionLayout), TextManager.Get("EventEditor.AddAction"), font: GUI.SubHeadingFont);

            GUILayoutGroup addActionDropdownLayout = new GUILayoutGroup(RectTransform(1.0f, 0.5f, addActionLayout), isHorizontal: true, childAnchor: Anchor.CenterLeft);
            GUIDropDown    addActionDropdown       = new GUIDropDown(RectTransform(0.8f, 1.0f, addActionDropdownLayout), elementCount: 10);
            GUIButton      addActionButton         = new GUIButton(RectTransform(0.2f, 1.0f, addActionDropdownLayout), TextManager.Get("EventEditor.Add"));

            // === ADD VALUE === //
            GUILayoutGroup addValueLayout = new GUILayoutGroup(RectTransform(1.0f, 0.125f, layoutGroup));

            new GUITextBlock(RectTransform(1.0f, 0.5f, addValueLayout), TextManager.Get("EventEditor.AddValue"), font: GUI.SubHeadingFont);

            GUILayoutGroup addValueDropdownLayout = new GUILayoutGroup(RectTransform(1.0f, 0.5f, addValueLayout), isHorizontal: true, childAnchor: Anchor.CenterLeft);
            GUIDropDown    addValueDropdown       = new GUIDropDown(RectTransform(0.8f, 1.0f, addValueDropdownLayout), elementCount: 7);
            GUIButton      addValueButton         = new GUIButton(RectTransform(0.2f, 1.0f, addValueDropdownLayout), TextManager.Get("EventEditor.Add"));

            // === ADD SPECIAL === //
            GUILayoutGroup addSpecialLayout = new GUILayoutGroup(RectTransform(1.0f, 0.125f, layoutGroup));

            new GUITextBlock(RectTransform(1.0f, 0.5f, addSpecialLayout), TextManager.Get("EventEditor.AddSpecial"), font: GUI.SubHeadingFont);
            GUILayoutGroup addSpecialDropdownLayout = new GUILayoutGroup(RectTransform(1.0f, 0.5f, addSpecialLayout), isHorizontal: true, childAnchor: Anchor.CenterLeft);
            GUIDropDown    addSpecialDropdown       = new GUIDropDown(RectTransform(0.8f, 1.0f, addSpecialDropdownLayout), elementCount: 1);
            GUIButton      addSpecialButton         = new GUIButton(RectTransform(0.2f, 1.0f, addSpecialDropdownLayout), TextManager.Get("EventEditor.Add"));

            // Add event prefabs with identifiers to the list
            foreach (EventPrefab eventPrefab in EventSet.GetAllEventPrefabs().Where(prefab => !string.IsNullOrWhiteSpace(prefab.Identifier)).Distinct())
            {
                loadDropdown.AddItem(eventPrefab.Identifier, eventPrefab);
            }

            // Add all types that inherit the EventAction class
            foreach (Type type in Assembly.GetExecutingAssembly().GetTypes().Where(type => type.IsSubclassOf(typeof(EventAction))))
            {
                addActionDropdown.AddItem(type.Name, type);
            }

            addSpecialDropdown.AddItem("Custom", typeof(CustomNode));

            addValueDropdown.AddItem(nameof(Single), typeof(float));
            addValueDropdown.AddItem(nameof(Boolean), typeof(bool));
            addValueDropdown.AddItem(nameof(String), typeof(string));
            addValueDropdown.AddItem(nameof(SpawnType), typeof(SpawnType));
            addValueDropdown.AddItem(nameof(LimbType), typeof(LimbType));
            addValueDropdown.AddItem(nameof(ReputationAction.ReputationType), typeof(ReputationAction.ReputationType));
            addValueDropdown.AddItem(nameof(SpawnAction.SpawnLocationType), typeof(SpawnAction.SpawnLocationType));

            loadButton.OnClicked          += (button, o) => Load(loadDropdown.SelectedData as EventPrefab);
            addActionButton.OnClicked     += (button, o) => AddAction(addActionDropdown.SelectedData as Type);
            addValueButton.OnClicked      += (button, o) => AddValue(addValueDropdown.SelectedData as Type);
            addSpecialButton.OnClicked    += (button, o) => AddSpecial(addSpecialDropdown.SelectedData as Type);
            exportProjectButton.OnClicked += ExportEventToFile;
            saveProjectButton.OnClicked   += SaveProjectToFile;
            newProjectButton.OnClicked    += TryCreateNewProject;
            loadProjectButton.OnClicked   += (button, o) =>
            {
                FileSelection.OnFileSelected = (file) =>
                {
                    XDocument?document = XMLExtensions.TryLoadXml(file);
                    if (document?.Root != null)
                    {
                        Load(document.Root);
                    }
                };

                string directory = Path.GetFullPath("EventProjects");
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }

                FileSelection.ClearFileTypeFilters();
                FileSelection.AddFileTypeFilter("Scripted Event", "*.sevproj");
                FileSelection.SelectFileTypeFilter("*.sevproj");
                FileSelection.CurrentDirectory = directory;
                FileSelection.Open             = true;
                return(true);
            };
            screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
        }
        private void CreateEvents(EventSet eventSet, Random rand)
        {
            if (level == null)
            {
                return;
            }
            int applyCount = 1;
            List <Func <Level.InterestingPosition, bool> > spawnPosFilter = new List <Func <Level.InterestingPosition, bool> >();

            if (eventSet.PerRuin)
            {
                applyCount = Level.Loaded.Ruins.Count();
                foreach (var ruin in Level.Loaded.Ruins)
                {
                    spawnPosFilter.Add((Level.InterestingPosition pos) => { return(pos.Ruin == ruin); });
                }
            }
            else if (eventSet.PerCave)
            {
                applyCount = Level.Loaded.Caves.Count();
                foreach (var cave in Level.Loaded.Caves)
                {
                    spawnPosFilter.Add((Level.InterestingPosition pos) => { return(pos.Cave == cave); });
                }
            }
            else if (eventSet.PerWreck)
            {
                var wrecks = Submarine.Loaded.Where(s => s.Info.IsWreck && (s.WreckAI == null || !s.WreckAI.IsAlive));
                applyCount = wrecks.Count();
                foreach (var wreck in wrecks)
                {
                    spawnPosFilter.Add((Level.InterestingPosition pos) => { return(pos.Submarine == wreck); });
                }
            }
            for (int i = 0; i < applyCount; i++)
            {
                if (eventSet.ChooseRandom)
                {
                    if (eventSet.EventPrefabs.Count > 0)
                    {
                        List <Pair <EventPrefab, float> > unusedEvents = new List <Pair <EventPrefab, float> >(eventSet.EventPrefabs);
                        for (int j = 0; j < eventSet.EventCount; j++)
                        {
                            var eventPrefab = ToolBox.SelectWeightedRandom(unusedEvents, unusedEvents.Select(e => CalculateCommonness(e)).ToList(), rand);
                            if (eventPrefab != null)
                            {
                                var newEvent = eventPrefab.First.CreateInstance();
                                if (newEvent == null)
                                {
                                    continue;
                                }
                                newEvent.Init(true);
                                if (i < spawnPosFilter.Count)
                                {
                                    newEvent.SpawnPosFilter = spawnPosFilter[i];
                                }
                                DebugConsole.Log("Initialized event " + newEvent.ToString());
                                if (!selectedEvents.ContainsKey(eventSet))
                                {
                                    selectedEvents.Add(eventSet, new List <Event>());
                                }
                                selectedEvents[eventSet].Add(newEvent);
                                unusedEvents.Remove(eventPrefab);
                            }
                        }
                    }
                    if (eventSet.ChildSets.Count > 0)
                    {
                        var newEventSet = SelectRandomEvents(eventSet.ChildSets);
                        if (newEventSet != null)
                        {
                            CreateEvents(newEventSet, rand);
                        }
                    }
                }
                else
                {
                    foreach (Pair <EventPrefab, float> eventPrefab in eventSet.EventPrefabs)
                    {
                        var newEvent = eventPrefab.First.CreateInstance();
                        if (newEvent == null)
                        {
                            continue;
                        }
                        newEvent.Init(true);
                        DebugConsole.Log("Initialized event " + newEvent.ToString());
                        if (!selectedEvents.ContainsKey(eventSet))
                        {
                            selectedEvents.Add(eventSet, new List <Event>());
                        }
                        selectedEvents[eventSet].Add(newEvent);
                    }

                    foreach (EventSet childEventSet in eventSet.ChildSets)
                    {
                        CreateEvents(childEventSet, rand);
                    }
                }
            }
        }