public void Init() { CharacterPrefab.LoadAll(); MissionPrefab.Init(); TraitorMissionPrefab.Init(); MapEntityPrefab.Init(); MapGenerationParams.Init(); LevelGenerationParams.LoadPresets(); ScriptedEventSet.LoadPrefabs(); Order.Init(); EventManagerSettings.Init(); AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions)); SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings)); StructurePrefab.LoadAll(GetFilesOfType(ContentType.Structure)); ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item)); JobPrefab.LoadAll(GetFilesOfType(ContentType.Jobs)); CorpsePrefab.LoadAll(GetFilesOfType(ContentType.Corpses)); NPCConversation.LoadAll(GetFilesOfType(ContentType.NPCConversations)); ItemAssemblyPrefab.LoadAll(); LevelObjectPrefab.LoadAll(); GameModePreset.Init(); LocationType.Init(); SubmarineInfo.RefreshSavedSubs(); Screen.SelectNull(); NetLobbyScreen = new NetLobbyScreen(); CheckContentPackage(); }
public void Init() { MissionPrefab.Init(); MapEntityPrefab.Init(); MapGenerationParams.Init(); LevelGenerationParams.LoadPresets(); ScriptedEventSet.LoadPrefabs(); AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions)); StructurePrefab.LoadAll(GetFilesOfType(ContentType.Structure)); ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item)); JobPrefab.LoadAll(GetFilesOfType(ContentType.Jobs)); ItemAssemblyPrefab.LoadAll(); NPCConversation.LoadAll(GetFilesOfType(ContentType.NPCConversations)); ItemAssemblyPrefab.LoadAll(); LevelObjectPrefab.LoadAll(); GameModePreset.Init(); LocationType.Init(); Submarine.RefreshSavedSubs(); Screen.SelectNull(); NetLobbyScreen = new NetLobbyScreen(); CheckContentPackage(); }
private void PlaceObject(LevelObjectPrefab prefab, SpawnPosition spawnPosition, Level level) { float rotation = 0.0f; if (prefab.AlignWithSurface && spawnPosition.Normal.LengthSquared() > 0.001f && spawnPosition != null) { rotation = MathUtils.VectorToAngle(new Vector2(spawnPosition.Normal.Y, spawnPosition.Normal.X)); } rotation += Rand.Range(prefab.RandomRotationRad.X, prefab.RandomRotationRad.Y, Rand.RandSync.Server); Vector2 position = Vector2.Zero; Vector2 edgeDir = Vector2.UnitX; if (spawnPosition == null) { position = new Vector2( Rand.Range(0.0f, level.Size.X, Rand.RandSync.Server), Rand.Range(0.0f, level.Size.Y, Rand.RandSync.Server)); } else { edgeDir = (spawnPosition.GraphEdge.Point1 - spawnPosition.GraphEdge.Point2) / spawnPosition.Length; position = spawnPosition.GraphEdge.Point2 + edgeDir * Rand.Range(prefab.MinSurfaceWidth / 2.0f, spawnPosition.Length - prefab.MinSurfaceWidth / 2.0f, Rand.RandSync.Server); } if (!MathUtils.NearlyEqual(prefab.RandomOffset.X, 0.0f) || !MathUtils.NearlyEqual(prefab.RandomOffset.Y, 0.0f)) { Vector2 offsetDir = spawnPosition.Normal.LengthSquared() > 0.001f ? spawnPosition.Normal : Rand.Vector(1.0f, Rand.RandSync.Server); position += offsetDir * Rand.Range(prefab.RandomOffset.X, prefab.RandomOffset.Y, Rand.RandSync.Server); } var newObject = new LevelObject(prefab, new Vector3(position, Rand.Range(prefab.DepthRange.X, prefab.DepthRange.Y, Rand.RandSync.Server)), Rand.Range(prefab.MinSize, prefab.MaxSize, Rand.RandSync.Server), rotation); AddObject(newObject, level); foreach (LevelObjectPrefab.ChildObject child in prefab.ChildObjects) { int childCount = Rand.Range(child.MinCount, child.MaxCount, Rand.RandSync.Server); for (int j = 0; j < childCount; j++) { var matchingPrefabs = LevelObjectPrefab.List.Where(p => child.AllowedNames.Contains(p.Name)); int prefabCount = matchingPrefabs.Count(); var childPrefab = prefabCount == 0 ? null : matchingPrefabs.ElementAt(Rand.Range(0, prefabCount, Rand.RandSync.Server)); if (childPrefab == null) { continue; } Vector2 childPos = position + edgeDir * Rand.Range(-0.5f, 0.5f, Rand.RandSync.Server) * prefab.MinSurfaceWidth; var childObject = new LevelObject(childPrefab, new Vector3(childPos, Rand.Range(childPrefab.DepthRange.X, childPrefab.DepthRange.Y, Rand.RandSync.Server)), Rand.Range(childPrefab.MinSize, childPrefab.MaxSize, Rand.RandSync.Server), rotation + Rand.Range(childPrefab.RandomRotationRad.X, childPrefab.RandomRotationRad.Y, Rand.RandSync.Server)); AddObject(childObject, level); } } }
public float GetSpawnProbability(LevelObjectPrefab prefab) { if (prefab.ClusteringAmount <= 0.0f) { return(Length); } float noise = (noiseVal + PerlinNoise.GetPerlin(prefab.ClusteringGroup, prefab.ClusteringGroup * 0.3f)) % 1.0f; return(Length * (float)Math.Pow(noise, prefab.ClusteringAmount)); }
private void LoadElements(XElement element, int parentTriggerIndex) { foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString().ToLowerInvariant()) { case "sprite": Sprites.Add(new Sprite(subElement, lazyLoad: true)); break; case "specularsprite": SpecularSprites.Add(new Sprite(subElement, lazyLoad: true)); break; case "deformablesprite": DeformableSprite = new DeformableSprite(subElement, lazyLoad: true); break; case "overridecommonness": string levelType = subElement.GetAttributeString("leveltype", ""); if (!OverrideCommonness.ContainsKey(levelType)) { OverrideCommonness.Add(levelType, subElement.GetAttributeFloat("commonness", 1.0f)); } break; case "leveltrigger": case "trigger": OverrideProperties.Add(null); LevelTriggerElements.Add(subElement); LoadElements(subElement, LevelTriggerElements.Count - 1); break; case "childobject": ChildObjects.Add(new ChildObject(subElement)); break; case "overrideproperties": var propertyOverride = new LevelObjectPrefab(subElement); OverrideProperties[OverrideProperties.Count - 1] = propertyOverride; if (!propertyOverride.Sprites.Any() && propertyOverride.DeformableSprite == null) { propertyOverride.Sprites = Sprites; propertyOverride.DeformableSprite = DeformableSprite; } break; case "body": case "physicsbody": PhysicsBodyElement = subElement; PhysicsBodyTriggerIndex = parentTriggerIndex; break; } } }
public LevelObject(LevelObjectPrefab prefab, Vector3 position, float scale, float rotation = 0.0f) { ActivePrefab = Prefab = prefab; Position = position; Scale = scale; Rotation = rotation; spriteIndex = ActivePrefab.Sprites.Any() ? Rand.Int(ActivePrefab.Sprites.Count, Rand.RandSync.Server) : -1; if (Sprite != null && prefab.SpriteSpecificPhysicsBodyElements.ContainsKey(Sprite)) { PhysicsBody = new PhysicsBody(prefab.SpriteSpecificPhysicsBodyElements[Sprite], ConvertUnits.ToSimUnits(new Vector2(position.X, position.Y)), Scale); } else if (prefab.PhysicsBodyElement != null) { PhysicsBody = new PhysicsBody(prefab.PhysicsBodyElement, ConvertUnits.ToSimUnits(new Vector2(position.X, position.Y)), Scale); } if (PhysicsBody != null) { PhysicsBody.SetTransformIgnoreContacts(PhysicsBody.SimPosition, -Rotation); PhysicsBody.BodyType = BodyType.Static; PhysicsBody.CollisionCategories = Physics.CollisionLevel; PhysicsBody.CollidesWith = Physics.CollisionWall | Physics.CollisionCharacter; } foreach (XElement triggerElement in prefab.LevelTriggerElements) { Triggers ??= new List <LevelTrigger>(); Vector2 triggerPosition = triggerElement.GetAttributeVector2("position", Vector2.Zero) * scale; if (rotation != 0.0f) { var ca = (float)Math.Cos(rotation); var sa = (float)Math.Sin(rotation); triggerPosition = new Vector2( ca * triggerPosition.X + sa * triggerPosition.Y, -sa * triggerPosition.X + ca * triggerPosition.Y); } var newTrigger = new LevelTrigger(triggerElement, new Vector2(position.X, position.Y) + triggerPosition, -rotation, scale, prefab.Name); int parentTriggerIndex = prefab.LevelTriggerElements.IndexOf(triggerElement.Parent); if (parentTriggerIndex > -1) { newTrigger.ParentTrigger = Triggers[parentTriggerIndex]; } Triggers.Add(newTrigger); } NeedsUpdate = NeedsNetworkSyncing || (Triggers != null && Triggers.Any()) || Prefab.PhysicsBodyTriggerIndex > -1; InitProjSpecific(); }
public float GetSpawnProbability(LevelObjectPrefab prefab) { if (prefab.ClusteringAmount <= 0.0f) { return(Length); } float noise = (float)( PerlinNoise.CalculatePerlin(GraphEdge.Point1.X / 10000.0f, GraphEdge.Point1.Y / 10000.0f, prefab.ClusteringGroup) + PerlinNoise.CalculatePerlin(GraphEdge.Point1.X / 20000.0f, GraphEdge.Point1.Y / 20000.0f, prefab.ClusteringGroup)); return(Length * (float)Math.Pow(noise, prefab.ClusteringAmount)); }
public LevelObject(LevelObjectPrefab prefab, Vector3 position, float scale, float rotation = 0.0f) { Triggers = new List <LevelTrigger>(); ActivePrefab = Prefab = prefab; Position = position; Scale = scale; Rotation = rotation; spriteIndex = ActivePrefab.Sprites.Any() ? Rand.Int(ActivePrefab.Sprites.Count, Rand.RandSync.Server) : -1; if (prefab.PhysicsBodyElement != null) { PhysicsBody = new PhysicsBody(prefab.PhysicsBodyElement, ConvertUnits.ToSimUnits(new Vector2(position.X, position.Y)), Scale); } foreach (XElement triggerElement in prefab.LevelTriggerElements) { Vector2 triggerPosition = triggerElement.GetAttributeVector2("position", Vector2.Zero) * scale; if (rotation != 0.0f) { var ca = (float)Math.Cos(rotation); var sa = (float)Math.Sin(rotation); triggerPosition = new Vector2( ca * triggerPosition.X + sa * triggerPosition.Y, -sa * triggerPosition.X + ca * triggerPosition.Y); } var newTrigger = new LevelTrigger(triggerElement, new Vector2(position.X, position.Y) + triggerPosition, -rotation, scale, prefab.Name); int parentTriggerIndex = prefab.LevelTriggerElements.IndexOf(triggerElement.Parent); if (parentTriggerIndex > -1) { newTrigger.ParentTrigger = Triggers[parentTriggerIndex]; } Triggers.Add(newTrigger); } InitProjSpecific(); }
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(); }
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); }
private IEnumerable <object> Load() { if (GameSettings.VerboseLogging) { DebugConsole.NewMessage("LOADING COROUTINE", Color.Lime); } SoundManager = new Sounds.SoundManager(); SoundManager.SetCategoryGainMultiplier("default", Config.SoundVolume); SoundManager.SetCategoryGainMultiplier("ui", Config.SoundVolume); SoundManager.SetCategoryGainMultiplier("waterambience", Config.SoundVolume); SoundManager.SetCategoryGainMultiplier("music", Config.MusicVolume); GUI.Init(Window, Config.SelectedContentPackages, GraphicsDevice); DebugConsole.Init(); SteamManager.Initialize(); if (SelectedPackages.Count == 0) { DebugConsole.Log("No content packages selected"); } else { DebugConsole.Log("Selected content packages: " + string.Join(", ", SelectedPackages.Select(cp => cp.Name))); } InitUserStats(); yield return(CoroutineStatus.Running); LightManager = new Lights.LightManager(base.GraphicsDevice, Content); WaterRenderer.Instance = new WaterRenderer(base.GraphicsDevice, Content); TitleScreen.LoadState = 1.0f; yield return(CoroutineStatus.Running); GUI.LoadContent(); TitleScreen.LoadState = 2.0f; yield return(CoroutineStatus.Running); MissionPrefab.Init(); MapEntityPrefab.Init(); Tutorials.Tutorial.Init(); MapGenerationParams.Init(); LevelGenerationParams.LoadPresets(); ScriptedEventSet.LoadPrefabs(); AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions)); TitleScreen.LoadState = 10.0f; yield return(CoroutineStatus.Running); StructurePrefab.LoadAll(GetFilesOfType(ContentType.Structure)); TitleScreen.LoadState = 15.0f; yield return(CoroutineStatus.Running); ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item)); TitleScreen.LoadState = 30.0f; yield return(CoroutineStatus.Running); JobPrefab.LoadAll(GetFilesOfType(ContentType.Jobs)); // Add any missing jobs from the prefab into Config.JobNamePreferences. foreach (JobPrefab job in JobPrefab.List) { if (!Config.JobPreferences.Contains(job.Identifier)) { Config.JobPreferences.Add(job.Identifier); } } NPCConversation.LoadAll(GetFilesOfType(ContentType.NPCConversations)); ItemAssemblyPrefab.LoadAll(); TitleScreen.LoadState = 35.0f; yield return(CoroutineStatus.Running); Debug.WriteLine("sounds"); CoroutineManager.StartCoroutine(SoundPlayer.Init()); int i = 0; while (!SoundPlayer.Initialized) { i++; TitleScreen.LoadState = SoundPlayer.SoundCount == 0 ? 30.0f : Math.Min(30.0f + 40.0f * i / Math.Max(SoundPlayer.SoundCount, 1), 70.0f); yield return(CoroutineStatus.Running); } TitleScreen.LoadState = 70.0f; yield return(CoroutineStatus.Running); GameModePreset.Init(); Submarine.RefreshSavedSubs(); TitleScreen.LoadState = 80.0f; yield return(CoroutineStatus.Running); GameScreen = new GameScreen(GraphicsDeviceManager.GraphicsDevice, Content); TitleScreen.LoadState = 90.0f; yield return(CoroutineStatus.Running); MainMenuScreen = new MainMenuScreen(this); LobbyScreen = new LobbyScreen(); ServerListScreen = new ServerListScreen(); if (SteamManager.USE_STEAM) { SteamWorkshopScreen = new SteamWorkshopScreen(); } SubEditorScreen = new SubEditorScreen(); ParticleEditorScreen = new ParticleEditorScreen(); LevelEditorScreen = new LevelEditorScreen(); SpriteEditorScreen = new SpriteEditorScreen(); CharacterEditorScreen = new CharacterEditorScreen(); yield return(CoroutineStatus.Running); ParticleManager = new ParticleManager(GameScreen.Cam); ParticleManager.LoadPrefabs(); LevelObjectPrefab.LoadAll(); DecalManager = new DecalManager(); yield return(CoroutineStatus.Running); LocationType.Init(); MainMenuScreen.Select(); TitleScreen.LoadState = 100.0f; hasLoaded = true; if (GameSettings.VerboseLogging) { DebugConsole.NewMessage("LOADING COROUTINE FINISHED", Color.Lime); } yield return(CoroutineStatus.Success); }
public GUIMessageBox Create() { var box = new GUIMessageBox(TextManager.Get("leveleditor.createlevelobj"), string.Empty, new string[] { TextManager.Get("cancel"), TextManager.Get("done") }, new Vector2(0.5f, 0.8f)); box.Content.ChildAnchor = Anchor.TopCenter; box.Content.AbsoluteSpacing = 20; int elementSize = 30; var listBox = new GUIListBox(new RectTransform(new Vector2(1, 0.9f), box.Content.RectTransform)); new GUITextBlock(new RectTransform(new Point(listBox.Content.Rect.Width, elementSize), listBox.Content.RectTransform), TextManager.Get("leveleditor.levelobjname")) { CanBeFocused = false }; var nameBox = new GUITextBox(new RectTransform(new Point(listBox.Content.Rect.Width, elementSize), listBox.Content.RectTransform)); new GUITextBlock(new RectTransform(new Point(listBox.Content.Rect.Width, elementSize), listBox.Content.RectTransform), TextManager.Get("leveleditor.levelobjtexturepath")) { CanBeFocused = false }; var texturePathBox = new GUITextBox(new RectTransform(new Point(listBox.Content.Rect.Width, elementSize), listBox.Content.RectTransform)); foreach (LevelObjectPrefab prefab in LevelObjectPrefab.List) { if (prefab.Sprites.FirstOrDefault() == null) { continue; } texturePathBox.Text = Path.GetDirectoryName(prefab.Sprites.FirstOrDefault().FilePath); break; } newPrefab = new LevelObjectPrefab(null); new SerializableEntityEditor(listBox.Content.RectTransform, newPrefab, false, false); box.Buttons[0].OnClicked += (b, d) => { box.Close(); return(true); }; // Next box.Buttons[1].OnClicked += (b, d) => { if (string.IsNullOrEmpty(nameBox.Text)) { nameBox.Flash(GUI.Style.Red); GUI.AddMessage(TextManager.Get("leveleditor.levelobjnameempty"), GUI.Style.Red); return(false); } if (LevelObjectPrefab.List.Any(obj => obj.Name.ToLower() == nameBox.Text.ToLower())) { nameBox.Flash(GUI.Style.Red); GUI.AddMessage(TextManager.Get("leveleditor.levelobjnametaken"), GUI.Style.Red); return(false); } if (!File.Exists(texturePathBox.Text)) { texturePathBox.Flash(GUI.Style.Red); GUI.AddMessage(TextManager.Get("leveleditor.levelobjtexturenotfound"), GUI.Style.Red); return(false); } newPrefab.Name = nameBox.Text; XmlWriterSettings settings = new XmlWriterSettings { Indent = true }; foreach (ContentFile configFile in GameMain.Instance.GetFilesOfType(ContentType.LevelObjectPrefabs)) { XDocument doc = XMLExtensions.TryLoadXml(configFile.Path); if (doc == null) { continue; } var newElement = new XElement(newPrefab.Name); newPrefab.Save(newElement); newElement.Add(new XElement("Sprite", new XAttribute("texture", texturePathBox.Text), new XAttribute("sourcerect", "0,0,100,100"), new XAttribute("origin", "0.5,0.5"))); doc.Root.Add(newElement); using (var writer = XmlWriter.Create(configFile.Path, settings)) { doc.WriteTo(writer); writer.Flush(); } // Recreate the prefab so that the sprite loads correctly: TODO: consider a better way to do this newPrefab = new LevelObjectPrefab(newElement); break; } LevelObjectPrefab.List.Add(newPrefab); GameMain.LevelEditorScreen.UpdateLevelObjectsList(); box.Close(); return(true); }; return(box); }
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", Config.VoiceChatVolume * 20.0f, 0); if (ConsoleArguments.Contains("-skipintro")) { Config.EnableSplashScreen = false; } if (Config.EnableSplashScreen) { var pendingSplashScreens = TitleScreen.PendingSplashScreens; pendingSplashScreens?.Enqueue(new Pair <string, Point>("Content/Splash_UTG.mp4", new Point(1280, 720))); pendingSplashScreens?.Enqueue(new Pair <string, Point>("Content/Splash_FF.mp4", new Point(1280, 720))); pendingSplashScreens?.Enqueue(new Pair <string, Point>("Content/Splash_Daedalic.mp4", new Point(1920, 1080))); } //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.SelectedContentPackages, GraphicsDevice); DebugConsole.Init(); if (Config.AutoUpdateWorkshopItems) { if (SteamManager.AutoUpdateWorkshopItems()) { ContentPackage.LoadAll(); Config.ReloadContentPackages(); } } if (SelectedPackages.Count == 0) { DebugConsole.Log("No content packages selected"); } else { DebugConsole.Log("Selected content packages: " + string.Join(", ", SelectedPackages.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); MissionPrefab.Init(); MapEntityPrefab.Init(); Tutorials.Tutorial.Init(); MapGenerationParams.Init(); LevelGenerationParams.LoadPresets(); ScriptedEventSet.LoadPrefabs(); AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions)); TitleScreen.LoadState = 50.0f; yield return(CoroutineStatus.Running); StructurePrefab.LoadAll(GetFilesOfType(ContentType.Structure)); TitleScreen.LoadState = 53.0f; yield return(CoroutineStatus.Running); ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item)); TitleScreen.LoadState = 55.0f; yield return(CoroutineStatus.Running); JobPrefab.LoadAll(GetFilesOfType(ContentType.Jobs)); // Add any missing jobs from the prefab into Config.JobNamePreferences. foreach (JobPrefab job in JobPrefab.List) { if (!Config.JobPreferences.Contains(job.Identifier)) { Config.JobPreferences.Add(job.Identifier); } } NPCConversation.LoadAll(GetFilesOfType(ContentType.NPCConversations)); ItemAssemblyPrefab.LoadAll(); TitleScreen.LoadState = 60.0f; yield return(CoroutineStatus.Running); GameModePreset.Init(); Submarine.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); LobbyScreen = new LobbyScreen(); ServerListScreen = new ServerListScreen(); TitleScreen.LoadState = 70.0f; yield return(CoroutineStatus.Running); if (SteamManager.USE_STEAM) { SteamWorkshopScreen = new SteamWorkshopScreen(); if (SteamManager.IsInitialized) { SteamManager.Instance.Friends.OnInvitedToGame += OnInvitedToGame; SteamManager.Instance.Lobby.OnLobbyJoinRequested += OnLobbyJoinRequested; } } 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(); CharacterEditorScreen = new CharacterEditorScreen(); 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(); CheckContentPackage(); 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); }
private void CreateLevelObjectEditor(LevelObjectPrefab levelObjectPrefab) { editorContainer.ClearChildren(); var editor = new SerializableEntityEditor(editorContainer.Content.RectTransform, levelObjectPrefab, false, true, elementHeight: 20, titleFont: GUI.LargeFont); if (selectedParams != null) { var commonnessContainer = new GUILayoutGroup(new RectTransform(new Point(editor.Rect.Width, 70)) { IsFixedSize = true }, isHorizontal: false, childAnchor: Anchor.TopCenter) { AbsoluteSpacing = 5, Stretch = true }; new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.4f), commonnessContainer.RectTransform), TextManager.GetWithVariable("leveleditor.levelobjcommonness", "[leveltype]", selectedParams.Name), textAlignment: Alignment.Center); new GUINumberInput(new RectTransform(new Vector2(0.5f, 0.4f), commonnessContainer.RectTransform), GUINumberInput.NumberType.Float) { MinValueFloat = 0, MaxValueFloat = 100, FloatValue = levelObjectPrefab.GetCommonness(selectedParams.Name), OnValueChanged = (numberInput) => { levelObjectPrefab.OverrideCommonness[selectedParams.Name] = numberInput.FloatValue; } }; new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), commonnessContainer.RectTransform), style: null); editor.AddCustomContent(commonnessContainer, 1); } Sprite sprite = levelObjectPrefab.Sprites.FirstOrDefault() ?? levelObjectPrefab.DeformableSprite?.Sprite; if (sprite != null) { editor.AddCustomContent(new GUIButton(new RectTransform(new Point(editor.Rect.Width / 2, (int)(25 * GUI.Scale))) { IsFixedSize = true }, TextManager.Get("leveleditor.editsprite")) { OnClicked = (btn, userdata) => { editingSprite = sprite; GameMain.SpriteEditorScreen.SelectSprite(editingSprite); return(true); } }, 1); } if (levelObjectPrefab.DeformableSprite != null) { var deformEditor = levelObjectPrefab.DeformableSprite.CreateEditor(editor, levelObjectPrefab.SpriteDeformations, levelObjectPrefab.Name); deformEditor.GetChild <GUIDropDown>().OnSelected += (selected, userdata) => { CreateLevelObjectEditor(selectedLevelObject); return(true); }; editor.AddCustomContent(deformEditor, editor.ContentCount); } //child object editing new GUITextBlock(new RectTransform(new Point(editor.Rect.Width, 40), editorContainer.Content.RectTransform), TextManager.Get("leveleditor.childobjects"), font: GUI.SubHeadingFont, textAlignment: Alignment.BottomCenter); foreach (LevelObjectPrefab.ChildObject childObj in levelObjectPrefab.ChildObjects) { var childObjFrame = new GUIFrame(new RectTransform(new Point(editor.Rect.Width, 30))); var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), childObjFrame.RectTransform, Anchor.Center), isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f }; var selectedChildObj = childObj; var dropdown = new GUIDropDown(new RectTransform(new Vector2(0.5f, 1.0f), paddedFrame.RectTransform), elementCount: 10, selectMultiple: true); foreach (LevelObjectPrefab objPrefab in LevelObjectPrefab.List) { dropdown.AddItem(objPrefab.Name, objPrefab); if (childObj.AllowedNames.Contains(objPrefab.Name)) { dropdown.SelectItem(objPrefab); } } dropdown.OnSelected = (selected, obj) => { childObj.AllowedNames = dropdown.SelectedDataMultiple.Select(d => ((LevelObjectPrefab)d).Name).ToList(); return(true); }; new GUINumberInput(new RectTransform(new Vector2(0.2f, 1.0f), paddedFrame.RectTransform), GUINumberInput.NumberType.Int) { MinValueInt = 0, MaxValueInt = 10, OnValueChanged = (numberInput) => { selectedChildObj.MinCount = numberInput.IntValue; selectedChildObj.MaxCount = Math.Max(selectedChildObj.MaxCount, selectedChildObj.MinCount); } }.IntValue = childObj.MinCount; new GUINumberInput(new RectTransform(new Vector2(0.2f, 1.0f), paddedFrame.RectTransform), GUINumberInput.NumberType.Int) { MinValueInt = 0, MaxValueInt = 10, OnValueChanged = (numberInput) => { selectedChildObj.MaxCount = numberInput.IntValue; selectedChildObj.MinCount = Math.Min(selectedChildObj.MaxCount, selectedChildObj.MinCount); } }.IntValue = childObj.MaxCount; new GUIButton(new RectTransform(new Vector2(0.1f, 1.0f), paddedFrame.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUICancelButton") { OnClicked = (btn, userdata) => { selectedLevelObject.ChildObjects.Remove(selectedChildObj); CreateLevelObjectEditor(selectedLevelObject); return(true); } }; childObjFrame.RectTransform.Parent = editorContainer.Content.RectTransform; } var buttonContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), editorContainer.Content.RectTransform), style: null); new GUIButton(new RectTransform(new Point(editor.Rect.Width / 2, 20), buttonContainer.RectTransform, Anchor.Center), TextManager.Get("leveleditor.addchildobject")) { OnClicked = (btn, userdata) => { selectedLevelObject.ChildObjects.Add(new LevelObjectPrefab.ChildObject()); CreateLevelObjectEditor(selectedLevelObject); return(true); } }; buttonContainer.RectTransform.MinSize = buttonContainer.RectTransform.Children.First().MinSize; //light editing new GUITextBlock(new RectTransform(new Point(editor.Rect.Width, 40), editorContainer.Content.RectTransform), TextManager.Get("leveleditor.lightsources"), textAlignment: Alignment.BottomCenter, font: GUI.SubHeadingFont); foreach (LightSourceParams lightSourceParams in selectedLevelObject.LightSourceParams) { new SerializableEntityEditor(editorContainer.Content.RectTransform, lightSourceParams, inGame: false, showName: true); } buttonContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), editorContainer.Content.RectTransform), style: null); new GUIButton(new RectTransform(new Point(editor.Rect.Width / 2, 20), buttonContainer.RectTransform, Anchor.Center), TextManager.Get("leveleditor.addlightsource")) { OnClicked = (btn, userdata) => { selectedLevelObject.LightSourceTriggerIndex.Add(-1); selectedLevelObject.LightSourceParams.Add(new LightSourceParams(100.0f, Color.White)); CreateLevelObjectEditor(selectedLevelObject); return(true); } }; buttonContainer.RectTransform.MinSize = buttonContainer.RectTransform.Children.First().MinSize; }
public LevelEditorScreen() { cam = new Camera() { MinZoom = 0.01f, MaxZoom = 1.0f }; leftPanel = new GUIFrame(new RectTransform(new Vector2(0.125f, 0.8f), Frame.RectTransform) { MinSize = new Point(150, 0) }); var paddedLeftPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), leftPanel.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.02f, 0.0f) }) { Stretch = true, RelativeSpacing = 0.01f }; paramsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.3f), paddedLeftPanel.RectTransform)); paramsList.OnSelected += (GUIComponent component, object obj) => { selectedParams = obj as LevelGenerationParams; editorContainer.ClearChildren(); SortLevelObjectsList(selectedParams); new SerializableEntityEditor(editorContainer.Content.RectTransform, selectedParams, false, true, elementHeight: 20); return(true); }; ruinParamsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), paddedLeftPanel.RectTransform)); ruinParamsList.OnSelected += (GUIComponent component, object obj) => { var ruinGenerationParams = obj as RuinGenerationParams; editorContainer.ClearChildren(); new SerializableEntityEditor(editorContainer.Content.RectTransform, ruinGenerationParams, false, true, elementHeight: 20); return(true); }; new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.createlevelobj")) { OnClicked = (btn, obj) => { Wizard.Instance.Create(); return(true); } }; lightingEnabled = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.025f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.lightingenabled")); cursorLightEnabled = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.025f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.cursorlightenabled")); new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.reloadtextures")) { OnClicked = (btn, obj) => { Level.Loaded?.ReloadTextures(); return(true); } }; new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedLeftPanel.RectTransform), TextManager.Get("editor.saveall")) { OnClicked = (btn, obj) => { SerializeAll(); return(true); } }; rightPanel = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f), Frame.RectTransform, Anchor.TopRight) { MinSize = new Point(450, 0) }); var paddedRightPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), rightPanel.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.02f, 0.0f) }) { Stretch = true, RelativeSpacing = 0.01f }; editorContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), paddedRightPanel.RectTransform)); var seedContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), paddedRightPanel.RectTransform), isHorizontal: true); new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), seedContainer.RectTransform), TextManager.Get("leveleditor.levelseed")); seedBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), seedContainer.RectTransform), ToolBox.RandomSeed(8)); new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedRightPanel.RectTransform), TextManager.Get("leveleditor.generate")) { OnClicked = (btn, obj) => { Submarine.Unload(); GameMain.LightManager.ClearLights(); Level.CreateRandom(seedBox.Text, generationParams: selectedParams).Generate(mirror: false); GameMain.LightManager.AddLight(pointerLightSource); cam.Position = new Vector2(Level.Loaded.Size.X / 2, Level.Loaded.Size.Y / 2); foreach (GUITextBlock param in paramsList.Content.Children) { param.TextColor = param.UserData == selectedParams ? GUI.Style.Green : param.Style.TextColor; } seedBox.Deselect(); return(true); } }; bottomPanel = new GUIFrame(new RectTransform(new Vector2(0.75f, 0.22f), Frame.RectTransform, Anchor.BottomLeft) { MaxSize = new Point(GameMain.GraphicsWidth - rightPanel.Rect.Width, 1000) }, style: "GUIFrameBottom"); levelObjectList = new GUIListBox(new RectTransform(new Vector2(0.99f, 0.85f), bottomPanel.RectTransform, Anchor.Center)) { UseGridLayout = true }; levelObjectList.OnSelected += (GUIComponent component, object obj) => { selectedLevelObject = obj as LevelObjectPrefab; CreateLevelObjectEditor(selectedLevelObject); return(true); }; spriteEditDoneButton = new GUIButton(new RectTransform(new Point(200, 30), anchor: Anchor.BottomRight) { AbsoluteOffset = new Point(20, 20) }, TextManager.Get("leveleditor.spriteeditdone")) { OnClicked = (btn, userdata) => { editingSprite = null; return(true); } }; topPanel = new GUIFrame(new RectTransform(new Point(400, 100), GUI.Canvas) { RelativeOffset = new Vector2(leftPanel.RectTransform.RelativeSize.X * 2, 0.0f) }, style: "GUIFrameTop"); }
public GUIMessageBox Create() { var box = new GUIMessageBox(TextManager.Get("LevelEditorCreateLevelObj"), string.Empty, new string[] { TextManager.Get("Cancel"), TextManager.Get("Done") }, GameMain.GraphicsWidth / 2, (int)(GameMain.GraphicsHeight * 0.8f)); box.Content.ChildAnchor = Anchor.TopCenter; box.Content.AbsoluteSpacing = 20; int elementSize = 30; var listBox = new GUIListBox(new RectTransform(new Vector2(1, 0.9f), box.Content.RectTransform)); new GUITextBlock(new RectTransform(new Point(listBox.Content.Rect.Width, elementSize), listBox.Content.RectTransform), TextManager.Get("LevelEditorLevelObjName")) { CanBeFocused = false }; var nameBox = new GUITextBox(new RectTransform(new Point(listBox.Content.Rect.Width, elementSize), listBox.Content.RectTransform)); new GUITextBlock(new RectTransform(new Point(listBox.Content.Rect.Width, elementSize), listBox.Content.RectTransform), TextManager.Get("LevelEditorLevelObjTexturePath")) { CanBeFocused = false }; var texturePathBox = new GUITextBox(new RectTransform(new Point(listBox.Content.Rect.Width, elementSize), listBox.Content.RectTransform)); foreach (LevelObjectPrefab prefab in LevelObjectPrefab.List) { if (prefab.Sprite == null) continue; texturePathBox.Text = Path.GetDirectoryName(prefab.Sprite.FilePath); break; } newPrefab = new LevelObjectPrefab(null); new SerializableEntityEditor(listBox.Content.RectTransform, newPrefab, false, false); box.Buttons[0].OnClicked += (b, d) => { box.Close(); return true; }; // Next box.Buttons[1].OnClicked += (b, d) => { if (string.IsNullOrEmpty(nameBox.Text)) { nameBox.Flash(Color.Red); GUI.AddMessage(TextManager.Get("LevelEditorLevelObjNameEmpty"), Color.Red); return false; } if (LevelObjectPrefab.List.Any(obj => obj.Name.ToLower() == nameBox.Text.ToLower())) { nameBox.Flash(Color.Red); GUI.AddMessage(TextManager.Get("LevelEditorLevelObjNameTaken"), Color.Red); return false; } if (!File.Exists(texturePathBox.Text)) { texturePathBox.Flash(Color.Red); GUI.AddMessage(TextManager.Get("LevelEditorLevelObjTextureNotFound"), Color.Red); return false; } newPrefab.Name = nameBox.Text; XmlWriterSettings settings = new XmlWriterSettings { Indent = true }; foreach (string configFile in GameMain.Instance.GetFilesOfType(ContentType.LevelObjectPrefabs)) { XDocument doc = XMLExtensions.TryLoadXml(configFile); if (doc?.Root == null) continue; var newElement = new XElement(newPrefab.Name); newPrefab.Save(newElement); newElement.Add(new XElement("Sprite", new XAttribute("texture", texturePathBox.Text), new XAttribute("sourcerect", "0,0,100,100"), new XAttribute("origin", "0.5,0.5"))); doc.Root.Add(newElement); using (var writer = XmlWriter.Create(configFile, settings)) { doc.WriteTo(writer); writer.Flush(); } break; } LevelObjectPrefab.List.Add(newPrefab); GameMain.LevelEditorScreen.UpdateLevelObjectsList(); box.Close(); return true; }; return box; }
public void PlaceObjects(Level level, int amount) { objectGrid = new List <LevelObject> [ level.Size.X / GridSize, (level.Size.Y - level.BottomPos) / GridSize]; List <SpawnPosition> availableSpawnPositions = new List <SpawnPosition>(); var levelCells = level.GetAllCells(); availableSpawnPositions.AddRange(GetAvailableSpawnPositions(levelCells, LevelObjectPrefab.SpawnPosType.Wall)); availableSpawnPositions.AddRange(GetAvailableSpawnPositions(level.SeaFloor.Cells, LevelObjectPrefab.SpawnPosType.SeaFloor)); foreach (Structure structure in Structure.WallList) { if (!structure.HasBody || structure.HiddenInGame) { continue; } if (level.Ruins.Any(r => r.Submarine == structure.Submarine)) { if (structure.IsHorizontal) { bool topHull = Hull.FindHull(structure.WorldPosition + Vector2.UnitY * 64) != null; bool bottomHull = Hull.FindHull(structure.WorldPosition - Vector2.UnitY * 64) != null; if (topHull && bottomHull) { continue; } availableSpawnPositions.Add(new SpawnPosition( new GraphEdge(new Vector2(structure.WorldRect.X, structure.WorldPosition.Y), new Vector2(structure.WorldRect.Right, structure.WorldPosition.Y)), bottomHull ? Vector2.UnitY : -Vector2.UnitY, LevelObjectPrefab.SpawnPosType.RuinWall, bottomHull ? Alignment.Bottom : Alignment.Top)); } else { bool rightHull = Hull.FindHull(structure.WorldPosition + Vector2.UnitX * 64) != null; bool leftHull = Hull.FindHull(structure.WorldPosition - Vector2.UnitX * 64) != null; if (rightHull && leftHull) { continue; } availableSpawnPositions.Add(new SpawnPosition( new GraphEdge(new Vector2(structure.WorldPosition.X, structure.WorldRect.Y), new Vector2(structure.WorldPosition.X, structure.WorldRect.Y - structure.WorldRect.Height)), leftHull ? Vector2.UnitX : -Vector2.UnitX, LevelObjectPrefab.SpawnPosType.RuinWall, leftHull ? Alignment.Left : Alignment.Right)); } } } foreach (var posOfInterest in level.PositionsOfInterest) { if (posOfInterest.PositionType != Level.PositionType.MainPath && posOfInterest.PositionType != Level.PositionType.SidePath) { continue; } availableSpawnPositions.Add(new SpawnPosition( new GraphEdge(posOfInterest.Position.ToVector2(), posOfInterest.Position.ToVector2() + Vector2.UnitX), Vector2.UnitY, LevelObjectPrefab.SpawnPosType.MainPath, Alignment.Top)); } availableSpawnPositions.Add(new SpawnPosition( new GraphEdge(level.StartPosition - Vector2.UnitX, level.StartPosition + Vector2.UnitX), -Vector2.UnitY, LevelObjectPrefab.SpawnPosType.LevelStart, Alignment.Top)); availableSpawnPositions.Add(new SpawnPosition( new GraphEdge(level.EndPosition - Vector2.UnitX, level.EndPosition + Vector2.UnitX), -Vector2.UnitY, LevelObjectPrefab.SpawnPosType.LevelEnd, Alignment.Top)); var availablePrefabs = new List <LevelObjectPrefab>(LevelObjectPrefab.List); objects = new List <LevelObject>(); updateableObjects = new List <LevelObject>(); Dictionary <LevelObjectPrefab, List <SpawnPosition> > suitableSpawnPositions = new Dictionary <LevelObjectPrefab, List <SpawnPosition> >(); Dictionary <LevelObjectPrefab, List <float> > spawnPositionWeights = new Dictionary <LevelObjectPrefab, List <float> >(); for (int i = 0; i < amount; i++) { //get a random prefab and find a place to spawn it LevelObjectPrefab prefab = GetRandomPrefab(level.GenerationParams, availablePrefabs); if (prefab == null) { continue; } if (!suitableSpawnPositions.ContainsKey(prefab)) { float minDistance = level.Size.X * 0.2f; suitableSpawnPositions.Add(prefab, availableSpawnPositions.Where(sp => sp.SpawnPosTypes.Any(type => prefab.SpawnPos.HasFlag(type)) && sp.Length >= prefab.MinSurfaceWidth && (prefab.AllowAtStart || !level.IsCloseToStart(sp.GraphEdge.Center, minDistance)) && (prefab.AllowAtEnd || !level.IsCloseToEnd(sp.GraphEdge.Center, minDistance)) && (sp.Alignment == Alignment.Any || prefab.Alignment.HasFlag(sp.Alignment))).ToList()); spawnPositionWeights.Add(prefab, suitableSpawnPositions[prefab].Select(sp => sp.GetSpawnProbability(prefab)).ToList()); } SpawnPosition spawnPosition = ToolBox.SelectWeightedRandom(suitableSpawnPositions[prefab], spawnPositionWeights[prefab], Rand.RandSync.Server); if (spawnPosition == null && prefab.SpawnPos != LevelObjectPrefab.SpawnPosType.None) { continue; } PlaceObject(prefab, spawnPosition, level); if (prefab.MaxCount < amount) { if (objects.Count(o => o.Prefab == prefab) >= prefab.MaxCount) { availablePrefabs.Remove(prefab); } } } foreach (Level.Cave cave in level.Caves) { availablePrefabs = new List <LevelObjectPrefab>(LevelObjectPrefab.List.FindAll(p => p.SpawnPos.HasFlag(LevelObjectPrefab.SpawnPosType.CaveWall))); availableSpawnPositions.Clear(); suitableSpawnPositions.Clear(); spawnPositionWeights.Clear(); var caveCells = cave.Tunnels.SelectMany(t => t.Cells); List <VoronoiCell> caveWallCells = new List <VoronoiCell>(); foreach (var edge in caveCells.SelectMany(c => c.Edges)) { if (!edge.NextToCave) { continue; } if (edge.Cell1?.CellType == CellType.Solid) { caveWallCells.Add(edge.Cell1); } if (edge.Cell2?.CellType == CellType.Solid) { caveWallCells.Add(edge.Cell2); } } availableSpawnPositions.AddRange(GetAvailableSpawnPositions(caveWallCells.Distinct(), LevelObjectPrefab.SpawnPosType.CaveWall)); for (int i = 0; i < cave.CaveGenerationParams.LevelObjectAmount; i++) { //get a random prefab and find a place to spawn it LevelObjectPrefab prefab = GetRandomPrefab(cave.CaveGenerationParams, availablePrefabs, requireCaveSpecificOverride: true); if (prefab == null) { continue; } if (!suitableSpawnPositions.ContainsKey(prefab)) { suitableSpawnPositions.Add(prefab, availableSpawnPositions.Where(sp => sp.Length >= prefab.MinSurfaceWidth && (sp.Alignment == Alignment.Any || prefab.Alignment.HasFlag(sp.Alignment))).ToList()); spawnPositionWeights.Add(prefab, suitableSpawnPositions[prefab].Select(sp => sp.GetSpawnProbability(prefab)).ToList()); } SpawnPosition spawnPosition = ToolBox.SelectWeightedRandom(suitableSpawnPositions[prefab], spawnPositionWeights[prefab], Rand.RandSync.Server); if (spawnPosition == null && prefab.SpawnPos != LevelObjectPrefab.SpawnPosType.None) { continue; } PlaceObject(prefab, spawnPosition, level, cave); if (prefab.MaxCount < amount) { if (objects.Count(o => o.Prefab == prefab && o.ParentCave == cave) >= prefab.MaxCount) { availablePrefabs.Remove(prefab); } } } } }
public LevelEditorScreen() { cam = new Camera() { MinZoom = 0.01f, MaxZoom = 1.0f }; leftPanel = new GUIFrame(new RectTransform(new Vector2(0.125f, 0.8f), Frame.RectTransform) { MinSize = new Point(150, 0) }); var paddedLeftPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), leftPanel.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.02f, 0.0f) }) { Stretch = true, RelativeSpacing = 0.01f }; paramsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.3f), paddedLeftPanel.RectTransform)); paramsList.OnSelected += (GUIComponent component, object obj) => { selectedParams = obj as LevelGenerationParams; editorContainer.ClearChildren(); SortLevelObjectsList(selectedParams); new SerializableEntityEditor(editorContainer.Content.RectTransform, selectedParams, false, true, elementHeight: 20); return(true); }; var ruinTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.ruinparams"), font: GUI.SubHeadingFont); ruinParamsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.1f), paddedLeftPanel.RectTransform)); ruinParamsList.OnSelected += (GUIComponent component, object obj) => { var ruinGenerationParams = obj as RuinGenerationParams; editorContainer.ClearChildren(); new SerializableEntityEditor(editorContainer.Content.RectTransform, ruinGenerationParams, false, true, elementHeight: 20); return(true); }; var outpostTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.outpostparams"), font: GUI.SubHeadingFont); GUITextBlock.AutoScaleAndNormalize(ruinTitle, outpostTitle); outpostParamsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), paddedLeftPanel.RectTransform)); outpostParamsList.OnSelected += (GUIComponent component, object obj) => { var outpostGenerationParams = obj as OutpostGenerationParams; editorContainer.ClearChildren(); var outpostParamsEditor = new SerializableEntityEditor(editorContainer.Content.RectTransform, outpostGenerationParams, false, true, elementHeight: 20); // location type ------------------------- var locationTypeGroup = new GUILayoutGroup(new RectTransform(new Point(editorContainer.Content.Rect.Width, 20)), isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true }; new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), locationTypeGroup.RectTransform), TextManager.Get("outpostmoduleallowedlocationtypes"), textAlignment: Alignment.CenterLeft); HashSet <string> availableLocationTypes = new HashSet <string> { "any" }; foreach (LocationType locationType in LocationType.List) { availableLocationTypes.Add(locationType.Identifier); } var locationTypeDropDown = new GUIDropDown(new RectTransform(new Vector2(0.5f, 1f), locationTypeGroup.RectTransform), text: string.Join(", ", outpostGenerationParams.AllowedLocationTypes.Select(lt => TextManager.Capitalize(lt)) ?? "any".ToEnumerable()), selectMultiple: true); foreach (string locationType in availableLocationTypes) { locationTypeDropDown.AddItem(TextManager.Capitalize(locationType), locationType); if (outpostGenerationParams.AllowedLocationTypes.Contains(locationType)) { locationTypeDropDown.SelectItem(locationType); } } if (!outpostGenerationParams.AllowedLocationTypes.Any()) { locationTypeDropDown.SelectItem("any"); } locationTypeDropDown.OnSelected += (_, __) => { outpostGenerationParams.SetAllowedLocationTypes(locationTypeDropDown.SelectedDataMultiple.Cast <string>()); locationTypeDropDown.Text = ToolBox.LimitString(locationTypeDropDown.Text, locationTypeDropDown.Font, locationTypeDropDown.Rect.Width); return(true); }; locationTypeGroup.RectTransform.MinSize = new Point(locationTypeGroup.Rect.Width, locationTypeGroup.RectTransform.Children.Max(c => c.MinSize.Y)); outpostParamsEditor.AddCustomContent(locationTypeGroup, 100); // module count ------------------------- var moduleLabel = new GUITextBlock(new RectTransform(new Point(editorContainer.Content.Rect.Width, (int)(70 * GUI.Scale))), TextManager.Get("submarinetype.outpostmodules"), font: GUI.SubHeadingFont); outpostParamsEditor.AddCustomContent(moduleLabel, 100); foreach (KeyValuePair <string, int> moduleCount in outpostGenerationParams.ModuleCounts) { var moduleCountGroup = new GUILayoutGroup(new RectTransform(new Point(editorContainer.Content.Rect.Width, (int)(25 * GUI.Scale))), isHorizontal: true, childAnchor: Anchor.CenterLeft); new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), moduleCountGroup.RectTransform), TextManager.Capitalize(moduleCount.Key), textAlignment: Alignment.CenterLeft); new GUINumberInput(new RectTransform(new Vector2(0.5f, 1f), moduleCountGroup.RectTransform), GUINumberInput.NumberType.Int) { MinValueInt = 0, MaxValueInt = 100, IntValue = moduleCount.Value, OnValueChanged = (numInput) => { outpostGenerationParams.SetModuleCount(moduleCount.Key, numInput.IntValue); if (numInput.IntValue == 0) { outpostParamsList.Select(outpostParamsList.SelectedData); } } }; moduleCountGroup.RectTransform.MinSize = new Point(moduleCountGroup.Rect.Width, moduleCountGroup.RectTransform.Children.Max(c => c.MinSize.Y)); outpostParamsEditor.AddCustomContent(moduleCountGroup, 100); } // add module count ------------------------- var addModuleCountGroup = new GUILayoutGroup(new RectTransform(new Point(editorContainer.Content.Rect.Width, (int)(40 * GUI.Scale))), isHorizontal: true, childAnchor: Anchor.Center); HashSet <string> availableFlags = new HashSet <string>(); foreach (string flag in OutpostGenerationParams.Params.SelectMany(p => p.ModuleCounts.Select(m => m.Key))) { availableFlags.Add(flag); } foreach (var sub in SubmarineInfo.SavedSubmarines) { if (sub.OutpostModuleInfo == null) { continue; } foreach (string flag in sub.OutpostModuleInfo.ModuleFlags) { availableFlags.Add(flag); } } var moduleTypeDropDown = new GUIDropDown(new RectTransform(new Vector2(0.8f, 0.8f), addModuleCountGroup.RectTransform), text: TextManager.Get("leveleditor.addmoduletype")); foreach (string flag in availableFlags) { if (outpostGenerationParams.ModuleCounts.Any(mc => mc.Key.Equals(flag, StringComparison.OrdinalIgnoreCase))) { continue; } moduleTypeDropDown.AddItem(TextManager.Capitalize(flag), flag); } moduleTypeDropDown.OnSelected += (_, userdata) => { outpostGenerationParams.SetModuleCount(userdata as string, 1); outpostParamsList.Select(outpostParamsList.SelectedData); return(true); }; addModuleCountGroup.RectTransform.MinSize = new Point(addModuleCountGroup.Rect.Width, addModuleCountGroup.RectTransform.Children.Max(c => c.MinSize.Y)); outpostParamsEditor.AddCustomContent(addModuleCountGroup, 100); return(true); }; var createLevelObjButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.createlevelobj")) { OnClicked = (btn, obj) => { Wizard.Instance.Create(); return(true); } }; GUITextBlock.AutoScaleAndNormalize(createLevelObjButton.TextBlock); lightingEnabled = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.025f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.lightingenabled")); cursorLightEnabled = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.025f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.cursorlightenabled")); new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.reloadtextures")) { OnClicked = (btn, obj) => { Level.Loaded?.ReloadTextures(); return(true); } }; new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedLeftPanel.RectTransform), TextManager.Get("editor.saveall")) { OnClicked = (btn, obj) => { SerializeAll(); return(true); } }; rightPanel = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f), Frame.RectTransform, Anchor.TopRight) { MinSize = new Point(450, 0) }); var paddedRightPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), rightPanel.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.02f, 0.0f) }) { Stretch = true, RelativeSpacing = 0.01f }; editorContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), paddedRightPanel.RectTransform)); var seedContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), paddedRightPanel.RectTransform), isHorizontal: true); new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), seedContainer.RectTransform), TextManager.Get("leveleditor.levelseed")); seedBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), seedContainer.RectTransform), ToolBox.RandomSeed(8)); new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedRightPanel.RectTransform), TextManager.Get("leveleditor.generate")) { OnClicked = (btn, obj) => { Submarine.Unload(); GameMain.LightManager.ClearLights(); LevelData levelData = LevelData.CreateRandom(seedBox.Text, generationParams: selectedParams); levelData.ForceOutpostGenerationParams = outpostParamsList.SelectedData as OutpostGenerationParams; Level.Generate(levelData, mirror: false); GameMain.LightManager.AddLight(pointerLightSource); cam.Position = new Vector2(Level.Loaded.Size.X / 2, Level.Loaded.Size.Y / 2); foreach (GUITextBlock param in paramsList.Content.Children) { param.TextColor = param.UserData == selectedParams ? GUI.Style.Green : param.Style.TextColor; } seedBox.Deselect(); return(true); } }; new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedRightPanel.RectTransform), TextManager.Get("leveleditor.test")) { OnClicked = (btn, obj) => { if (Level.Loaded?.LevelData == null) { return(false); } GameMain.GameScreen.Select(); var currEntities = Entity.GetEntities().ToList(); if (Submarine.MainSub != null) { var toRemove = Entity.GetEntities().Where(e => e.Submarine == Submarine.MainSub).ToList(); foreach (Entity ent in toRemove) { ent.Remove(); } Submarine.MainSub.Remove(); } //TODO: hacky workaround to check for wrecks and outposts, refactor SubmarineInfo and ContentType at some point var nonPlayerFiles = ContentPackage.GetFilesOfType(GameMain.Config.AllEnabledPackages, ContentType.Wreck).ToList(); nonPlayerFiles.AddRange(ContentPackage.GetFilesOfType(GameMain.Config.AllEnabledPackages, ContentType.Outpost)); nonPlayerFiles.AddRange(ContentPackage.GetFilesOfType(GameMain.Config.AllEnabledPackages, ContentType.OutpostModule)); SubmarineInfo subInfo = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name.Equals(GameMain.Config.QuickStartSubmarineName, StringComparison.InvariantCultureIgnoreCase)); subInfo ??= SubmarineInfo.SavedSubmarines.GetRandom(s => s.IsPlayer && !s.HasTag(SubmarineTag.Shuttle) && !nonPlayerFiles.Any(f => f.Path.CleanUpPath().Equals(s.FilePath.CleanUpPath(), StringComparison.InvariantCultureIgnoreCase))); GameSession gameSession = new GameSession(subInfo, "", GameModePreset.TestMode, null); gameSession.StartRound(Level.Loaded.LevelData); (gameSession.GameMode as TestGameMode).OnRoundEnd = () => { GameMain.LevelEditorScreen.Select(); Submarine.MainSub.Remove(); var toRemove = Entity.GetEntities().Where(e => !currEntities.Contains(e)).ToList(); foreach (Entity ent in toRemove) { ent.Remove(); } Submarine.MainSub = null; }; GameMain.GameSession = gameSession; return(true); } }; bottomPanel = new GUIFrame(new RectTransform(new Vector2(0.75f, 0.22f), Frame.RectTransform, Anchor.BottomLeft) { MaxSize = new Point(GameMain.GraphicsWidth - rightPanel.Rect.Width, 1000) }, style: "GUIFrameBottom"); levelObjectList = new GUIListBox(new RectTransform(new Vector2(0.99f, 0.85f), bottomPanel.RectTransform, Anchor.Center)) { UseGridLayout = true }; levelObjectList.OnSelected += (GUIComponent component, object obj) => { selectedLevelObject = obj as LevelObjectPrefab; CreateLevelObjectEditor(selectedLevelObject); return(true); }; spriteEditDoneButton = new GUIButton(new RectTransform(new Point(200, 30), anchor: Anchor.BottomRight) { AbsoluteOffset = new Point(20, 20) }, TextManager.Get("leveleditor.spriteeditdone")) { OnClicked = (btn, userdata) => { editingSprite = null; return(true); } }; topPanel = new GUIFrame(new RectTransform(new Point(400, 100), GUI.Canvas) { RelativeOffset = new Vector2(leftPanel.RectTransform.RelativeSize.X * 2, 0.0f) }, style: "GUIFrameTop"); }
public void PlaceObjects(Level level, int amount) { objectGrid = new List <LevelObject> [ level.Size.X / GridSize, (level.Size.Y - level.BottomPos) / GridSize]; List <SpawnPosition> availableSpawnPositions = new List <SpawnPosition>(); var levelCells = level.GetAllCells(); availableSpawnPositions.AddRange(GetAvailableSpawnPositions(levelCells, LevelObjectPrefab.SpawnPosType.Wall)); availableSpawnPositions.AddRange(GetAvailableSpawnPositions(level.SeaFloor.Cells, LevelObjectPrefab.SpawnPosType.SeaFloor)); foreach (RuinGeneration.Ruin ruin in level.Ruins) { foreach (var ruinShape in ruin.RuinShapes) { foreach (var wall in ruinShape.Walls) { availableSpawnPositions.Add(new SpawnPosition( new GraphEdge(wall.A, wall.B), (wall.A + wall.B) / 2.0f - ruinShape.Center, LevelObjectPrefab.SpawnPosType.RuinWall, ruinShape.GetLineAlignment(wall))); } } } foreach (var posOfInterest in level.PositionsOfInterest) { if (posOfInterest.PositionType != Level.PositionType.MainPath) { continue; } availableSpawnPositions.Add(new SpawnPosition( new GraphEdge(posOfInterest.Position.ToVector2(), posOfInterest.Position.ToVector2() + Vector2.UnitX), Vector2.UnitY, LevelObjectPrefab.SpawnPosType.MainPath, Alignment.Top)); } availableSpawnPositions.Add(new SpawnPosition( new GraphEdge(level.StartPosition - Vector2.UnitX, level.StartPosition + Vector2.UnitX), -Vector2.UnitY, LevelObjectPrefab.SpawnPosType.LevelStart, Alignment.Top)); availableSpawnPositions.Add(new SpawnPosition( new GraphEdge(level.EndPosition - Vector2.UnitX, level.EndPosition + Vector2.UnitX), -Vector2.UnitY, LevelObjectPrefab.SpawnPosType.LevelEnd, Alignment.Top)); var availablePrefabs = new List <LevelObjectPrefab>(LevelObjectPrefab.List); objects = new List <LevelObject>(); Dictionary <LevelObjectPrefab, List <SpawnPosition> > suitableSpawnPositions = new Dictionary <LevelObjectPrefab, List <SpawnPosition> >(); Dictionary <LevelObjectPrefab, List <float> > spawnPositionWeights = new Dictionary <LevelObjectPrefab, List <float> >(); for (int i = 0; i < amount; i++) { //get a random prefab and find a place to spawn it LevelObjectPrefab prefab = GetRandomPrefab(level.GenerationParams.Identifier, availablePrefabs); if (prefab == null) { continue; } if (!suitableSpawnPositions.ContainsKey(prefab)) { suitableSpawnPositions.Add(prefab, availableSpawnPositions.Where(sp => prefab.SpawnPos.HasFlag(sp.SpawnPosType) && (sp.Length >= prefab.MinSurfaceWidth && prefab.Alignment.HasFlag(sp.Alignment) || sp.SpawnPosType == LevelObjectPrefab.SpawnPosType.LevelEnd || sp.SpawnPosType == LevelObjectPrefab.SpawnPosType.LevelStart)).ToList()); spawnPositionWeights.Add(prefab, suitableSpawnPositions[prefab].Select(sp => sp.GetSpawnProbability(prefab)).ToList()); } SpawnPosition spawnPosition = ToolBox.SelectWeightedRandom(suitableSpawnPositions[prefab], spawnPositionWeights[prefab], Rand.RandSync.Server); if (spawnPosition == null && prefab.SpawnPos != LevelObjectPrefab.SpawnPosType.None) { continue; } float rotation = 0.0f; if (prefab.AlignWithSurface && spawnPosition != null) { rotation = MathUtils.VectorToAngle(new Vector2(spawnPosition.Normal.Y, spawnPosition.Normal.X)); } rotation += Rand.Range(prefab.RandomRotationRad.X, prefab.RandomRotationRad.Y, Rand.RandSync.Server); Vector2 position = Vector2.Zero; Vector2 edgeDir = Vector2.UnitX; if (spawnPosition == null) { position = new Vector2( Rand.Range(0.0f, level.Size.X, Rand.RandSync.Server), Rand.Range(0.0f, level.Size.Y, Rand.RandSync.Server)); } else { edgeDir = (spawnPosition.GraphEdge.Point1 - spawnPosition.GraphEdge.Point2) / spawnPosition.Length; position = spawnPosition.GraphEdge.Point2 + edgeDir * Rand.Range(prefab.MinSurfaceWidth / 2.0f, spawnPosition.Length - prefab.MinSurfaceWidth / 2.0f, Rand.RandSync.Server); } var newObject = new LevelObject(prefab, new Vector3(position, Rand.Range(prefab.DepthRange.X, prefab.DepthRange.Y, Rand.RandSync.Server)), Rand.Range(prefab.MinSize, prefab.MaxSize, Rand.RandSync.Server), rotation); AddObject(newObject, level); if (prefab.MaxCount < amount) { if (objects.Count(o => o.Prefab == prefab) >= prefab.MaxCount) { availablePrefabs.Remove(prefab); } } foreach (LevelObjectPrefab.ChildObject child in prefab.ChildObjects) { int childCount = Rand.Range(child.MinCount, child.MaxCount, Rand.RandSync.Server); for (int j = 0; j < childCount; j++) { var matchingPrefabs = LevelObjectPrefab.List.Where(p => child.AllowedNames.Contains(p.Name)); int prefabCount = matchingPrefabs.Count(); var childPrefab = prefabCount == 0 ? null : matchingPrefabs.ElementAt(Rand.Range(0, prefabCount, Rand.RandSync.Server)); if (childPrefab == null) { continue; } Vector2 childPos = position + edgeDir * Rand.Range(-0.5f, 0.5f, Rand.RandSync.Server) * prefab.MinSurfaceWidth; var childObject = new LevelObject(childPrefab, new Vector3(childPos, Rand.Range(childPrefab.DepthRange.X, childPrefab.DepthRange.Y, Rand.RandSync.Server)), Rand.Range(childPrefab.MinSize, childPrefab.MaxSize, Rand.RandSync.Server), rotation + Rand.Range(childPrefab.RandomRotationRad.X, childPrefab.RandomRotationRad.Y, Rand.RandSync.Server)); AddObject(childObject, level); } } } }
public void PlaceObjects(Level level, int amount) { objectGrid = new List <LevelObject> [ level.Size.X / GridSize, (level.Size.Y - level.BottomPos) / GridSize]; List <SpawnPosition> availableSpawnPositions = new List <SpawnPosition>(); var levelCells = level.GetAllCells(); availableSpawnPositions.AddRange(GetAvailableSpawnPositions(levelCells, LevelObjectPrefab.SpawnPosType.Wall)); availableSpawnPositions.AddRange(GetAvailableSpawnPositions(level.SeaFloor.Cells, LevelObjectPrefab.SpawnPosType.SeaFloor)); foreach (RuinGeneration.Ruin ruin in level.Ruins) { foreach (var ruinShape in ruin.RuinShapes) { foreach (var wall in ruinShape.Walls) { availableSpawnPositions.Add(new SpawnPosition( new GraphEdge(wall.A, wall.B), (wall.A + wall.B) / 2.0f - ruinShape.Center, LevelObjectPrefab.SpawnPosType.RuinWall, ruinShape.GetLineAlignment(wall))); } } } foreach (var posOfInterest in level.PositionsOfInterest) { if (posOfInterest.PositionType != Level.PositionType.MainPath && posOfInterest.PositionType != Level.PositionType.SidePath) { continue; } availableSpawnPositions.Add(new SpawnPosition( new GraphEdge(posOfInterest.Position.ToVector2(), posOfInterest.Position.ToVector2() + Vector2.UnitX), Vector2.UnitY, LevelObjectPrefab.SpawnPosType.MainPath, Alignment.Top)); } availableSpawnPositions.Add(new SpawnPosition( new GraphEdge(level.StartPosition - Vector2.UnitX, level.StartPosition + Vector2.UnitX), -Vector2.UnitY, LevelObjectPrefab.SpawnPosType.LevelStart, Alignment.Top)); availableSpawnPositions.Add(new SpawnPosition( new GraphEdge(level.EndPosition - Vector2.UnitX, level.EndPosition + Vector2.UnitX), -Vector2.UnitY, LevelObjectPrefab.SpawnPosType.LevelEnd, Alignment.Top)); var availablePrefabs = new List <LevelObjectPrefab>(LevelObjectPrefab.List); objects = new List <LevelObject>(); updateableObjects = new List <LevelObject>(); Dictionary <LevelObjectPrefab, List <SpawnPosition> > suitableSpawnPositions = new Dictionary <LevelObjectPrefab, List <SpawnPosition> >(); Dictionary <LevelObjectPrefab, List <float> > spawnPositionWeights = new Dictionary <LevelObjectPrefab, List <float> >(); for (int i = 0; i < amount; i++) { //get a random prefab and find a place to spawn it LevelObjectPrefab prefab = GetRandomPrefab(level.GenerationParams, availablePrefabs); if (prefab == null) { continue; } if (!suitableSpawnPositions.ContainsKey(prefab)) { suitableSpawnPositions.Add(prefab, availableSpawnPositions.Where(sp => sp.SpawnPosTypes.Any(type => prefab.SpawnPos.HasFlag(type)) && sp.Length >= prefab.MinSurfaceWidth && (sp.Alignment == Alignment.Any || prefab.Alignment.HasFlag(sp.Alignment))).ToList()); spawnPositionWeights.Add(prefab, suitableSpawnPositions[prefab].Select(sp => sp.GetSpawnProbability(prefab)).ToList()); } SpawnPosition spawnPosition = ToolBox.SelectWeightedRandom(suitableSpawnPositions[prefab], spawnPositionWeights[prefab], Rand.RandSync.Server); if (spawnPosition == null && prefab.SpawnPos != LevelObjectPrefab.SpawnPosType.None) { continue; } PlaceObject(prefab, spawnPosition, level); if (prefab.MaxCount < amount) { if (objects.Count(o => o.Prefab == prefab) >= prefab.MaxCount) { availablePrefabs.Remove(prefab); } } } foreach (Level.Cave cave in level.Caves) { availablePrefabs = new List <LevelObjectPrefab>(LevelObjectPrefab.List.FindAll(p => p.SpawnPos.HasFlag(LevelObjectPrefab.SpawnPosType.CaveWall))); availableSpawnPositions.Clear(); suitableSpawnPositions.Clear(); spawnPositionWeights.Clear(); var caveCells = cave.Tunnels.SelectMany(t => t.Cells); List <VoronoiCell> caveWallCells = new List <VoronoiCell>(); foreach (var edge in caveCells.SelectMany(c => c.Edges)) { if (!edge.NextToCave) { continue; } if (edge.Cell1?.CellType == CellType.Solid) { caveWallCells.Add(edge.Cell1); } if (edge.Cell2?.CellType == CellType.Solid) { caveWallCells.Add(edge.Cell2); } } availableSpawnPositions.AddRange(GetAvailableSpawnPositions(caveWallCells.Distinct(), LevelObjectPrefab.SpawnPosType.CaveWall)); for (int i = 0; i < cave.CaveGenerationParams.LevelObjectAmount; i++) { //get a random prefab and find a place to spawn it LevelObjectPrefab prefab = GetRandomPrefab(cave.CaveGenerationParams, availablePrefabs); if (prefab == null) { continue; } if (!suitableSpawnPositions.ContainsKey(prefab)) { suitableSpawnPositions.Add(prefab, availableSpawnPositions.Where(sp => sp.Length >= prefab.MinSurfaceWidth && (sp.Alignment == Alignment.Any || prefab.Alignment.HasFlag(sp.Alignment))).ToList()); spawnPositionWeights.Add(prefab, suitableSpawnPositions[prefab].Select(sp => sp.GetSpawnProbability(prefab)).ToList()); } SpawnPosition spawnPosition = ToolBox.SelectWeightedRandom(suitableSpawnPositions[prefab], spawnPositionWeights[prefab], Rand.RandSync.Server); if (spawnPosition == null && prefab.SpawnPos != LevelObjectPrefab.SpawnPosType.None) { continue; } PlaceObject(prefab, spawnPosition, level); if (prefab.MaxCount < amount) { if (objects.Count(o => o.Prefab == prefab) >= prefab.MaxCount) { availablePrefabs.Remove(prefab); } } } } }
private SpawnPosition FindObjectPosition(List <SpawnPosition> availableSpawnPositions, Level level, LevelObjectPrefab prefab) { if (prefab.SpawnPos == LevelObjectPrefab.SpawnPosType.None) { return(null); } var suitableSpawnPositions = availableSpawnPositions.Where(sp => prefab.SpawnPos.HasFlag(sp.SpawnPosType) && sp.Length >= prefab.MinSurfaceWidth && prefab.Alignment.HasFlag(sp.Alignment)).ToList(); return(ToolBox.SelectWeightedRandom(suitableSpawnPositions, suitableSpawnPositions.Select(sp => sp.GetSpawnProbability(prefab)).ToList(), Rand.RandSync.Server)); }
private IEnumerable <object> Load() { if (GameSettings.VerboseLogging) { DebugConsole.NewMessage("LOADING COROUTINE", Color.Lime); } SoundManager = new Sounds.SoundManager(); SoundManager.SetCategoryGainMultiplier("default", Config.SoundVolume); SoundManager.SetCategoryGainMultiplier("ui", Config.SoundVolume); SoundManager.SetCategoryGainMultiplier("waterambience", Config.SoundVolume); SoundManager.SetCategoryGainMultiplier("music", Config.MusicVolume); SoundManager.SetCategoryGainMultiplier("voip", Config.VoiceChatVolume); if (Config.EnableSplashScreen) { try { (TitleScreen as LoadingScreen).SplashScreen = new Video(base.GraphicsDevice, SoundManager, "Content/splashscreen.mp4", 1280, 720); } catch (Exception e) { Config.EnableSplashScreen = false; DebugConsole.ThrowError("Playing the splash screen failed.", e); } } GUI.Init(Window, Config.SelectedContentPackages, GraphicsDevice); DebugConsole.Init(); SteamManager.Initialize(); if (Config.AutoUpdateWorkshopItems) { if (SteamManager.AutoUpdateWorkshopItems()) { ContentPackage.LoadAll(ContentPackage.Folder); Config.ReloadContentPackages(); } } if (SelectedPackages.Count == 0) { DebugConsole.Log("No content packages selected"); } else { DebugConsole.Log("Selected content packages: " + string.Join(", ", SelectedPackages.Select(cp => cp.Name))); } #if DEBUG GameSettings.ShowUserStatisticsPrompt = false; GameSettings.SendUserStatistics = false; #endif InitUserStats(); yield return(CoroutineStatus.Running); LightManager = new Lights.LightManager(base.GraphicsDevice, Content); WaterRenderer.Instance = new WaterRenderer(base.GraphicsDevice, Content); TitleScreen.LoadState = 1.0f; yield return(CoroutineStatus.Running); GUI.LoadContent(); TitleScreen.LoadState = 2.0f; yield return(CoroutineStatus.Running); MissionPrefab.Init(); MapEntityPrefab.Init(); Tutorials.Tutorial.Init(); MapGenerationParams.Init(); LevelGenerationParams.LoadPresets(); ScriptedEventSet.LoadPrefabs(); AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions)); TitleScreen.LoadState = 10.0f; yield return(CoroutineStatus.Running); StructurePrefab.LoadAll(GetFilesOfType(ContentType.Structure)); TitleScreen.LoadState = 15.0f; yield return(CoroutineStatus.Running); ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item)); TitleScreen.LoadState = 25.0f; yield return(CoroutineStatus.Running); JobPrefab.LoadAll(GetFilesOfType(ContentType.Jobs)); // Add any missing jobs from the prefab into Config.JobNamePreferences. foreach (JobPrefab job in JobPrefab.List) { if (!Config.JobPreferences.Contains(job.Identifier)) { Config.JobPreferences.Add(job.Identifier); } } NPCConversation.LoadAll(GetFilesOfType(ContentType.NPCConversations)); ItemAssemblyPrefab.LoadAll(); TitleScreen.LoadState = 30.0f; 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 ? 30.0f : Math.Min(30.0f + 40.0f * i / Math.Max(SoundPlayer.SoundCount, 1), 70.0f); yield return(CoroutineStatus.Running); } TitleScreen.LoadState = 70.0f; yield return(CoroutineStatus.Running); GameModePreset.Init(); Submarine.RefreshSavedSubs(); TitleScreen.LoadState = 80.0f; yield return(CoroutineStatus.Running); GameScreen = new GameScreen(GraphicsDeviceManager.GraphicsDevice, Content); TitleScreen.LoadState = 90.0f; yield return(CoroutineStatus.Running); MainMenuScreen = new MainMenuScreen(this); LobbyScreen = new LobbyScreen(); ServerListScreen = new ServerListScreen(); if (SteamManager.USE_STEAM) { SteamWorkshopScreen = new SteamWorkshopScreen(); } SubEditorScreen = new SubEditorScreen(); ParticleEditorScreen = new ParticleEditorScreen(); LevelEditorScreen = new LevelEditorScreen(); SpriteEditorScreen = new SpriteEditorScreen(); CharacterEditorScreen = new CharacterEditorScreen(); yield return(CoroutineStatus.Running); TitleScreen.LoadState = 95.0f; ParticleManager = new ParticleManager(GameScreen.Cam); ParticleManager.LoadPrefabs(); TitleScreen.LoadState = 97.0f; LevelObjectPrefab.LoadAll(); DecalManager = new DecalManager(); TitleScreen.LoadState = 99.0f; yield return(CoroutineStatus.Running); LocationType.Init(); MainMenuScreen.Select(); CheckContentPackage(); TitleScreen.LoadState = 100.0f; hasLoaded = true; if (GameSettings.VerboseLogging) { DebugConsole.NewMessage("LOADING COROUTINE FINISHED", Color.Lime); } yield return(CoroutineStatus.Success); }
public void PlaceObjects(Level level, int amount) { objectGrid = new List <LevelObject> [ level.Size.X / GridSize, (level.Size.Y - level.BottomPos) / GridSize]; List <SpawnPosition> availableSpawnPositions = new List <SpawnPosition>(); var levelCells = level.GetAllCells(); availableSpawnPositions.AddRange(GetAvailableSpawnPositions(levelCells, LevelObjectPrefab.SpawnPosType.Wall)); availableSpawnPositions.AddRange(GetAvailableSpawnPositions(level.SeaFloor.Cells, LevelObjectPrefab.SpawnPosType.SeaFloor)); foreach (RuinGeneration.Ruin ruin in level.Ruins) { foreach (var ruinShape in ruin.RuinShapes) { foreach (var wall in ruinShape.Walls) { availableSpawnPositions.Add(new SpawnPosition( new GraphEdge(wall.A, wall.B), (wall.A + wall.B) / 2.0f - ruinShape.Center, LevelObjectPrefab.SpawnPosType.RuinWall, ruinShape.GetLineAlignment(wall))); } } } foreach (var posOfInterest in level.PositionsOfInterest) { if (posOfInterest.PositionType != Level.PositionType.MainPath) { continue; } availableSpawnPositions.Add(new SpawnPosition( new GraphEdge(posOfInterest.Position.ToVector2(), posOfInterest.Position.ToVector2() + Vector2.UnitX), Vector2.UnitY, LevelObjectPrefab.SpawnPosType.MainPath, Alignment.Top)); } objects = new List <LevelObject>(); for (int i = 0; i < amount; i++) { //get a random prefab and find a place to spawn it LevelObjectPrefab prefab = GetRandomPrefab(level.GenerationParams.Name); SpawnPosition spawnPosition = FindObjectPosition(availableSpawnPositions, level, prefab); if (spawnPosition == null && prefab.SpawnPos != LevelObjectPrefab.SpawnPosType.None) { continue; } float rotation = 0.0f; if (prefab.AlignWithSurface && spawnPosition != null) { rotation = MathUtils.VectorToAngle(new Vector2(spawnPosition.Normal.Y, spawnPosition.Normal.X)); } rotation += Rand.Range(prefab.RandomRotationRad.X, prefab.RandomRotationRad.Y, Rand.RandSync.Server); Vector2 position = Vector2.Zero; Vector2 edgeDir = Vector2.UnitX; if (spawnPosition == null) { position = new Vector2( Rand.Range(0.0f, level.Size.X, Rand.RandSync.Server), Rand.Range(0.0f, level.Size.Y, Rand.RandSync.Server)); } else { edgeDir = (spawnPosition.GraphEdge.Point1 - spawnPosition.GraphEdge.Point2) / spawnPosition.Length; position = spawnPosition.GraphEdge.Point2 + edgeDir * Rand.Range(prefab.MinSurfaceWidth / 2.0f, spawnPosition.Length - prefab.MinSurfaceWidth / 2.0f, Rand.RandSync.Server); } var newObject = new LevelObject(prefab, new Vector3(position, Rand.Range(prefab.DepthRange.X, prefab.DepthRange.Y, Rand.RandSync.Server)), Rand.Range(prefab.MinSize, prefab.MaxSize, Rand.RandSync.Server), rotation); AddObject(newObject, level); foreach (LevelObjectPrefab.ChildObject child in prefab.ChildObjects) { int childCount = Rand.Range(child.MinCount, child.MaxCount, Rand.RandSync.Server); for (int j = 0; j < childCount; j++) { var matchingPrefabs = LevelObjectPrefab.List.Where(p => child.AllowedNames.Contains(p.Name)); int prefabCount = matchingPrefabs.Count(); var childPrefab = prefabCount == 0 ? null : matchingPrefabs.ElementAt(Rand.Range(0, prefabCount, Rand.RandSync.Server)); if (childPrefab == null) { continue; } Vector2 childPos = position + edgeDir * Rand.Range(-0.5f, 0.5f, Rand.RandSync.Server) * prefab.MinSurfaceWidth; var childObject = new LevelObject(childPrefab, new Vector3(childPos, Rand.Range(childPrefab.DepthRange.X, childPrefab.DepthRange.Y, Rand.RandSync.Server)), Rand.Range(childPrefab.MinSize, childPrefab.MaxSize, Rand.RandSync.Server), rotation + Rand.Range(childPrefab.RandomRotationRad.X, childPrefab.RandomRotationRad.Y, Rand.RandSync.Server)); AddObject(childObject, level); } } } }
public void PlaceNestObjects(Level level, Level.Cave cave, Vector2 nestPosition, float nestRadius, int objectAmount) { Rand.SetSyncedSeed(ToolBox.StringToInt(level.Seed)); var availablePrefabs = new List <LevelObjectPrefab>(LevelObjectPrefab.List.FindAll(p => p.SpawnPos.HasFlag(LevelObjectPrefab.SpawnPosType.NestWall))); Dictionary <LevelObjectPrefab, List <SpawnPosition> > suitableSpawnPositions = new Dictionary <LevelObjectPrefab, List <SpawnPosition> >(); Dictionary <LevelObjectPrefab, List <float> > spawnPositionWeights = new Dictionary <LevelObjectPrefab, List <float> >(); List <SpawnPosition> availableSpawnPositions = new List <SpawnPosition>(); var caveCells = cave.Tunnels.SelectMany(t => t.Cells); List <VoronoiCell> caveWallCells = new List <VoronoiCell>(); foreach (var edge in caveCells.SelectMany(c => c.Edges)) { if (!edge.NextToCave) { continue; } if (MathUtils.LineSegmentToPointDistanceSquared(edge.Point1.ToPoint(), edge.Point2.ToPoint(), nestPosition.ToPoint()) > nestRadius * nestRadius) { continue; } if (edge.Cell1?.CellType == CellType.Solid) { caveWallCells.Add(edge.Cell1); } if (edge.Cell2?.CellType == CellType.Solid) { caveWallCells.Add(edge.Cell2); } } availableSpawnPositions.AddRange(GetAvailableSpawnPositions(caveWallCells.Distinct(), LevelObjectPrefab.SpawnPosType.CaveWall)); for (int i = 0; i < objectAmount; i++) { //get a random prefab and find a place to spawn it LevelObjectPrefab prefab = GetRandomPrefab(cave.CaveGenerationParams, availablePrefabs, requireCaveSpecificOverride: false); if (prefab == null) { continue; } if (!suitableSpawnPositions.ContainsKey(prefab)) { suitableSpawnPositions.Add(prefab, availableSpawnPositions.Where(sp => sp.Length >= prefab.MinSurfaceWidth && (sp.Alignment == Alignment.Any || prefab.Alignment.HasFlag(sp.Alignment))).ToList()); spawnPositionWeights.Add(prefab, suitableSpawnPositions[prefab].Select(sp => sp.GetSpawnProbability(prefab)).ToList()); } SpawnPosition spawnPosition = ToolBox.SelectWeightedRandom(suitableSpawnPositions[prefab], spawnPositionWeights[prefab], Rand.RandSync.Server); if (spawnPosition == null && prefab.SpawnPos != LevelObjectPrefab.SpawnPosType.None) { continue; } PlaceObject(prefab, spawnPosition, level); if (objects.Count(o => o.Prefab == prefab) >= prefab.MaxCount) { availablePrefabs.Remove(prefab); } } }