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, 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 override void Update(float deltaTime) { if (IsClient) { foreach (Item item in items) { if (item.ParentInventory != null && item.body != null) { item.body.FarseerBody.BodyType = BodyType.Dynamic; } } return; } switch (State) { case 0: foreach (Item item in items) { if (item.ParentInventory != null && item.body != null) { item.body.FarseerBody.BodyType = BodyType.Dynamic; } if (statusEffectOnApproach.ContainsKey(item)) { foreach (Character character in Character.CharacterList) { if (character.IsPlayer && Vector2.DistanceSquared(nestPosition, character.WorldPosition) < approachItemsRadius * approachItemsRadius) { statusEffectOnApproach[item].Apply(statusEffectOnApproach[item].type, 1.0f, item, item); statusEffectOnApproach.Remove(item); break; } } } } if (monsterPrefabs.Any()) { foreach (Character character in Character.CharacterList) { if (character.IsPlayer && Vector2.DistanceSquared(nestPosition, character.WorldPosition) < monsterSpawnRadius * monsterSpawnRadius) { foreach (var monster in monsterPrefabs) { int amount = Rand.Range(monster.Item2.X, monster.Item2.Y + 1); for (int i = 0; i < amount; i++) { Character.Create(monster.Item1.Identifier, nestPosition + Rand.Vector(100.0f), ToolBox.RandomSeed(8), createNetworkEvent: true); } } monsterPrefabs.Clear(); break; } } } //continue when all items are in the sub or destroyed if (AllItemsDestroyedOrRetrieved()) { State = 1; } break; case 1: if (!Submarine.MainSub.AtEndExit && !Submarine.MainSub.AtStartExit) { return; } State = 2; break; } }
private static void InitProjectSpecific() { commands.Add(new Command("autohull", "", (string[] args) => { if (Screen.Selected != GameMain.SubEditorScreen) { return; } if (MapEntity.mapEntityList.Any(e => e is Hull || e is Gap)) { ShowQuestionPrompt("This submarine already has hulls and/or gaps. This command will delete them. Do you want to continue? Y/N", (option) => { if (option.ToLower() == "y") { GameMain.SubEditorScreen.AutoHull(); } }); } else { GameMain.SubEditorScreen.AutoHull(); } })); commands.Add(new Command("startclient", "", (string[] args) => { if (args.Length == 0) { return; } if (GameMain.Client == null) { GameMain.NetworkMember = new GameClient("Name"); GameMain.Client.ConnectToServer(args[0]); } })); commands.Add(new Command("mainmenuscreen|mainmenu|menu", "mainmenu/menu: Go to the main menu.", (string[] args) => { GameMain.GameSession = null; List <Character> characters = new List <Character>(Character.CharacterList); foreach (Character c in characters) { c.Remove(); } GameMain.MainMenuScreen.Select(); })); commands.Add(new Command("gamescreen|game", "gamescreen/game: Go to the \"in-game\" view.", (string[] args) => { GameMain.GameScreen.Select(); })); commands.Add(new Command("editsubscreen|editsub|subeditor", "editsub/subeditor: Switch to the submarine editor.", (string[] args) => { if (args.Length > 0) { Submarine.Load(string.Join(" ", args), true); } GameMain.SubEditorScreen.Select(); })); commands.Add(new Command("editcharacter", "", (string[] args) => { GameMain.CharacterEditorScreen.Select(); })); commands.Add(new Command("editparticles", "", (string[] args) => { GameMain.ParticleEditorScreen.Select(); })); commands.Add(new Command("control|controlcharacter", "control [character name]: Start controlling the specified character.", (string[] args) => { if (args.Length < 1) { return; } var character = FindMatchingCharacter(args, true); if (character != null) { Character.Controlled = character; } }, () => { return(new string[][] { Character.CharacterList.Select(c => c.Name).Distinct().ToArray() }); })); commands.Add(new Command("shake", "", (string[] args) => { GameMain.GameScreen.Cam.Shake = 10.0f; })); commands.Add(new Command("los", "los: Toggle the line of sight effect on/off.", (string[] args) => { GameMain.LightManager.LosEnabled = !GameMain.LightManager.LosEnabled; NewMessage("Line of sight effect " + (GameMain.LightManager.LosEnabled ? "enabled" : "disabled"), Color.White); })); commands.Add(new Command("lighting|lights", "Toggle lighting on/off.", (string[] args) => { GameMain.LightManager.LightingEnabled = !GameMain.LightManager.LightingEnabled; NewMessage("Lighting " + (GameMain.LightManager.LightingEnabled ? "enabled" : "disabled"), Color.White); })); commands.Add(new Command("tutorial", "", (string[] args) => { TutorialMode.StartTutorial(Tutorials.TutorialType.TutorialTypes[0]); })); commands.Add(new Command("lobby|lobbyscreen", "", (string[] args) => { GameMain.LobbyScreen.Select(); })); commands.Add(new Command("save|savesub", "save [submarine name]: Save the currently loaded submarine using the specified name.", (string[] args) => { if (args.Length < 1) { return; } if (GameMain.SubEditorScreen.CharacterMode) { GameMain.SubEditorScreen.ToggleCharacterMode(); } string fileName = string.Join(" ", args); if (fileName.Contains("../")) { ThrowError("Illegal symbols in filename (../)"); return; } if (Submarine.SaveCurrent(System.IO.Path.Combine(Submarine.SavePath, fileName + ".sub"))) { NewMessage("Sub saved", Color.Green); } })); commands.Add(new Command("load|loadsub", "load [submarine name]: Load a submarine.", (string[] args) => { if (args.Length == 0) { return; } Submarine.Load(string.Join(" ", args), true); })); commands.Add(new Command("cleansub", "", (string[] args) => { for (int i = MapEntity.mapEntityList.Count - 1; i >= 0; i--) { MapEntity me = MapEntity.mapEntityList[i]; if (me.SimPosition.Length() > 2000.0f) { NewMessage("Removed " + me.Name + " (simposition " + me.SimPosition + ")", Color.Orange); MapEntity.mapEntityList.RemoveAt(i); } else if (!me.ShouldBeSaved) { NewMessage("Removed " + me.Name + " (!ShouldBeSaved)", Color.Orange); MapEntity.mapEntityList.RemoveAt(i); } else if (me is Item) { Item item = me as Item; var wire = item.GetComponent <Wire>(); if (wire == null) { continue; } if (wire.GetNodes().Count > 0 && !wire.Connections.Any(c => c != null)) { wire.Item.Drop(null); NewMessage("Dropped wire (ID: " + wire.Item.ID + ") - attached on wall but no connections found", Color.Orange); } } } })); commands.Add(new Command("messagebox", "", (string[] args) => { new GUIMessageBox("", string.Join(" ", args)); })); commands.Add(new Command("debugdraw", "debugdraw: Toggle the debug drawing mode on/off.", (string[] args) => { GameMain.DebugDraw = !GameMain.DebugDraw; NewMessage("Debug draw mode " + (GameMain.DebugDraw ? "enabled" : "disabled"), Color.White); })); commands.Add(new Command("fpscounter", "fpscounter: Toggle the FPS counter.", (string[] args) => { GameMain.ShowFPS = !GameMain.ShowFPS; NewMessage("FPS counter " + (GameMain.DebugDraw ? "enabled" : "disabled"), Color.White); })); commands.Add(new Command("togglehud|hud", "togglehud/hud: Toggle the character HUD (inventories, icons, buttons, etc) on/off.", (string[] args) => { GUI.DisableHUD = !GUI.DisableHUD; GameMain.Instance.IsMouseVisible = !GameMain.Instance.IsMouseVisible; NewMessage(GUI.DisableHUD ? "Disabled HUD" : "Enabled HUD", Color.White); })); commands.Add(new Command("followsub", "followsub: Toggle whether the camera should follow the nearest submarine.", (string[] args) => { Camera.FollowSub = !Camera.FollowSub; NewMessage(Camera.FollowSub ? "Set the camera to follow the closest submarine" : "Disabled submarine following.", Color.White); })); commands.Add(new Command("toggleaitargets|aitargets", "toggleaitargets/aitargets: Toggle the visibility of AI targets (= targets that enemies can detect and attack/escape from).", (string[] args) => { AITarget.ShowAITargets = !AITarget.ShowAITargets; NewMessage(AITarget.ShowAITargets ? "Enabled AI target drawing" : "Disabled AI target drawing", Color.White); })); #if DEBUG commands.Add(new Command("spamchatmessages", "", (string[] args) => { int msgCount = 1000; if (args.Length > 0) { int.TryParse(args[0], out msgCount); } int msgLength = 50; if (args.Length > 1) { int.TryParse(args[1], out msgLength); } for (int i = 0; i < msgCount; i++) { if (GameMain.Server != null) { GameMain.Server.SendChatMessage(ToolBox.RandomSeed(msgLength), ChatMessageType.Default); } else if (GameMain.Client != null) { GameMain.Client.SendChatMessage(ToolBox.RandomSeed(msgLength)); } } })); #endif commands.Add(new Command("cleanbuild", "", (string[] args) => { GameMain.Config.MusicVolume = 0.5f; GameMain.Config.SoundVolume = 0.5f; NewMessage("Music and sound volume set to 0.5", Color.Green); GameMain.Config.GraphicsWidth = 0; GameMain.Config.GraphicsHeight = 0; GameMain.Config.WindowMode = WindowMode.Fullscreen; NewMessage("Resolution set to 0 x 0 (screen resolution will be used)", Color.Green); NewMessage("Fullscreen enabled", Color.Green); GameSettings.ShowUserStatisticsPrompt = true; GameSettings.VerboseLogging = false; if (GameMain.Config.MasterServerUrl != "http://www.undertowgames.com/baromaster") { ThrowError("MasterServerUrl \"" + GameMain.Config.MasterServerUrl + "\"!"); } GameMain.Config.Save("config.xml"); var saveFiles = System.IO.Directory.GetFiles(SaveUtil.SaveFolder); foreach (string saveFile in saveFiles) { System.IO.File.Delete(saveFile); NewMessage("Deleted " + saveFile, Color.Green); } if (System.IO.Directory.Exists(System.IO.Path.Combine(SaveUtil.SaveFolder, "temp"))) { System.IO.Directory.Delete(System.IO.Path.Combine(SaveUtil.SaveFolder, "temp"), true); NewMessage("Deleted temp save folder", Color.Green); } if (System.IO.Directory.Exists(ServerLog.SavePath)) { var logFiles = System.IO.Directory.GetFiles(ServerLog.SavePath); foreach (string logFile in logFiles) { System.IO.File.Delete(logFile); NewMessage("Deleted " + logFile, Color.Green); } } if (System.IO.File.Exists("filelist.xml")) { System.IO.File.Delete("filelist.xml"); NewMessage("Deleted filelist", Color.Green); } if (System.IO.File.Exists("Data/bannedplayers.txt")) { System.IO.File.Delete("Data/bannedplayers.txt"); NewMessage("Deleted bannedplayers.txt", Color.Green); } if (System.IO.File.Exists("Submarines/TutorialSub.sub")) { System.IO.File.Delete("Submarines/TutorialSub.sub"); NewMessage("Deleted TutorialSub from the submarine folder", Color.Green); } if (System.IO.File.Exists(GameServer.SettingsFile)) { System.IO.File.Delete(GameServer.SettingsFile); NewMessage("Deleted server settings", Color.Green); } if (System.IO.File.Exists(GameServer.ClientPermissionsFile)) { System.IO.File.Delete(GameServer.ClientPermissionsFile); NewMessage("Deleted client permission file", Color.Green); } if (System.IO.File.Exists("crashreport.txt")) { System.IO.File.Delete("crashreport.txt"); NewMessage("Deleted crashreport.txt", Color.Green); } if (!System.IO.File.Exists("Content/Map/TutorialSub.sub")) { ThrowError("TutorialSub.sub not found!"); } })); }
private GameMode InstantiateGameMode(GameModePreset gameModePreset, string seed, SubmarineInfo selectedSub, CampaignSettings settings, IEnumerable <MissionPrefab> missionPrefabs = null, MissionType missionType = MissionType.None) { if (gameModePreset.GameModeType == typeof(CoOpMode) || gameModePreset.GameModeType == typeof(PvPMode)) { //don't allow hidden mission types (e.g. GoTo) in single mission modes var missionTypes = (MissionType[])Enum.GetValues(typeof(MissionType)); for (int i = 0; i < missionTypes.Length; i++) { if (MissionPrefab.HiddenMissionClasses.Contains(missionTypes[i])) { missionType &= ~missionTypes[i]; } } } if (gameModePreset.GameModeType == typeof(CoOpMode)) { return(missionPrefabs != null ? new CoOpMode(gameModePreset, missionPrefabs) : new CoOpMode(gameModePreset, missionType, seed ?? ToolBox.RandomSeed(8))); } else if (gameModePreset.GameModeType == typeof(PvPMode)) { return(missionPrefabs != null ? new PvPMode(gameModePreset, missionPrefabs) : new PvPMode(gameModePreset, missionType, seed ?? ToolBox.RandomSeed(8))); } else if (gameModePreset.GameModeType == typeof(MultiPlayerCampaign)) { var campaign = MultiPlayerCampaign.StartNew(seed ?? ToolBox.RandomSeed(8), selectedSub, settings); if (campaign != null && selectedSub != null) { campaign.Money = Math.Max(MultiPlayerCampaign.MinimumInitialMoney, campaign.Money - selectedSub.Price); } return(campaign); } #if CLIENT else if (gameModePreset.GameModeType == typeof(SinglePlayerCampaign)) { var campaign = SinglePlayerCampaign.StartNew(seed ?? ToolBox.RandomSeed(8), selectedSub, settings); if (campaign != null && selectedSub != null) { campaign.Money = Math.Max(SinglePlayerCampaign.MinimumInitialMoney, campaign.Money - selectedSub.Price); } return(campaign); } else if (gameModePreset.GameModeType == typeof(TutorialMode)) { return(new TutorialMode(gameModePreset)); } else if (gameModePreset.GameModeType == typeof(TestGameMode)) { return(new TestGameMode(gameModePreset)); } #endif else if (gameModePreset.GameModeType == typeof(GameMode)) { return(new GameMode(gameModePreset)); } else { throw new Exception($"Could not find a game mode of the type \"{gameModePreset.GameModeType}\""); } }
public void SetTextPos() { if (text == null) { return; } censoredText = ""; for (int i = 0; i < text.Length; i++) { censoredText += "\u2022"; } var rect = Rect; overflowClipActive = false; wrappedText = text; TextSize = MeasureText(text); if (Wrap && rect.Width > 0) { wrappedText = ToolBox.WrapText(text, rect.Width - padding.X - padding.Z, Font, textScale, playerInput); TextSize = MeasureText(wrappedText); } else if (OverflowClip) { overflowClipActive = TextSize.X > rect.Width - padding.X - padding.Z; } if (autoScale && textScale > 0.1f && (TextSize.X * textScale > rect.Width - padding.X - padding.Z || TextSize.Y * textScale > rect.Height - padding.Y - padding.W)) { TextScale = Math.Max(0.1f, Math.Min( (rect.Width - padding.X - padding.Z) / TextSize.X, (rect.Height - padding.Y - padding.W) / TextSize.Y)) - 0.01f; return; } textPos = new Vector2(padding.X + (rect.Width - padding.Z - padding.X) / 2.0f, padding.Y + (rect.Height - padding.Y - padding.W) / 2.0f); origin = TextSize * 0.5f; if (textAlignment.HasFlag(Alignment.Left) && !overflowClipActive) { textPos.X = padding.X; origin.X = 0; } if (textAlignment.HasFlag(Alignment.Right) || overflowClipActive) { textPos.X = rect.Width - padding.Z; origin.X = TextSize.X; } if (textAlignment.HasFlag(Alignment.Top)) { textPos.Y = padding.Y; origin.Y = 0; } if (textAlignment.HasFlag(Alignment.Bottom)) { textPos.Y = rect.Height - padding.W; origin.Y = TextSize.Y; } origin.X = (int)(origin.X); origin.Y = (int)(origin.Y); textPos.X = (int)textPos.X; textPos.Y = (int)textPos.Y; }
public GUIComponent CreateInfoFrame(GUIFrame frame, bool returnParent, Sprite permissionIcon = null) { var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.874f, 0.58f), frame.RectTransform, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.05f) }) { RelativeSpacing = 0.05f //Stretch = true }; var headerArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.322f), paddedFrame.RectTransform), isHorizontal: true); new GUICustomComponent(new RectTransform(new Vector2(0.425f, 1.0f), headerArea.RectTransform), onDraw: (sb, component) => DrawInfoFrameCharacterIcon(sb, component.Rect)); ScalableFont font = paddedFrame.Rect.Width < 280 ? GUI.SmallFont : GUI.Font; var headerTextArea = new GUILayoutGroup(new RectTransform(new Vector2(0.575f, 1.0f), headerArea.RectTransform)) { RelativeSpacing = 0.02f, Stretch = true }; Color?nameColor = null; if (Job != null) { nameColor = Job.Prefab.UIColor; } GUITextBlock characterNameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), headerTextArea.RectTransform), ToolBox.LimitString(Name, GUI.Font, headerTextArea.Rect.Width), textColor: nameColor, font: GUI.Font) { ForceUpperCase = true, Padding = Vector4.Zero }; if (permissionIcon != null) { Point iconSize = permissionIcon.SourceRect.Size; int iconWidth = (int)((float)characterNameBlock.Rect.Height / iconSize.Y * iconSize.X); new GUIImage(new RectTransform(new Point(iconWidth, characterNameBlock.Rect.Height), characterNameBlock.RectTransform) { AbsoluteOffset = new Point(-iconWidth - 2, 0) }, permissionIcon) { IgnoreLayoutGroups = true }; } if (Job != null) { new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), headerTextArea.RectTransform), Job.Name, textColor: Job.Prefab.UIColor, font: font) { Padding = Vector4.Zero }; } if (personalityTrait != null) { new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), headerTextArea.RectTransform), TextManager.AddPunctuation(':', TextManager.Get("PersonalityTrait"), TextManager.Get("personalitytrait." + personalityTrait.Name.Replace(" ", ""))), font: font) { Padding = Vector4.Zero }; } if (Job != null && (Character == null || !Character.IsDead)) { var skillsArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.63f), paddedFrame.RectTransform, Anchor.BottomCenter, Pivot.BottomCenter)) { Stretch = true }; var skills = Job.Skills; skills.Sort((s1, s2) => - s1.Level.CompareTo(s2.Level)); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), skillsArea.RectTransform), TextManager.AddPunctuation(':', TextManager.Get("skills"), string.Empty), font: font) { Padding = Vector4.Zero }; foreach (Skill skill in skills) { Color textColor = Color.White * (0.5f + skill.Level / 200.0f); var skillName = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), skillsArea.RectTransform), TextManager.Get("SkillName." + skill.Identifier), textColor: textColor, font: font) { Padding = Vector4.Zero }; new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), skillName.RectTransform), ((int)skill.Level).ToString(), textColor: textColor, font: font, textAlignment: Alignment.CenterRight); } } else if (Character != null && Character.IsDead) { var deadArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.63f), paddedFrame.RectTransform, Anchor.BottomCenter, Pivot.BottomCenter)) { Stretch = true }; string deadDescription = TextManager.AddPunctuation(':', TextManager.Get("deceased") + "\n" + Character.CauseOfDeath.Affliction?.CauseOfDeathDescription ?? TextManager.AddPunctuation(':', TextManager.Get("CauseOfDeath"), TextManager.Get("CauseOfDeath." + Character.CauseOfDeath.Type.ToString()))); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), deadArea.RectTransform), deadDescription, textColor: GUI.Style.Red, font: font, textAlignment: Alignment.TopLeft) { Padding = Vector4.Zero }; } if (returnParent) { return(frame); } else { return(paddedFrame); } }
public CampaignSetupUI(bool isMultiplayer, GUIComponent newGameContainer, GUIComponent loadGameContainer, IEnumerable <Submarine> submarines, IEnumerable <string> saveFiles = null) { this.isMultiplayer = isMultiplayer; this.newGameContainer = newGameContainer; this.loadGameContainer = loadGameContainer; var columnContainer = new GUILayoutGroup(new RectTransform(Vector2.One, newGameContainer.RectTransform), isHorizontal: true) { Stretch = true, RelativeSpacing = isMultiplayer ? 0.0f : 0.05f }; var leftColumn = new GUILayoutGroup(new RectTransform(Vector2.One, columnContainer.RectTransform)) { Stretch = true, RelativeSpacing = 0.015f }; var rightColumn = new GUILayoutGroup(new RectTransform(isMultiplayer ? Vector2.Zero : new Vector2(1.5f, 1.0f), columnContainer.RectTransform)) { Stretch = true, RelativeSpacing = 0.015f }; columnContainer.Recalculate(); // New game left side new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("SaveName")); saveNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, string.Empty) { textFilterFunction = (string str) => { return(ToolBox.RemoveInvalidFileNameChars(str)); } }; new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("MapSeed")); seedBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, ToolBox.RandomSeed(8)); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("SelectedSub")); var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), isHorizontal: true) { Stretch = true }; subList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.65f), leftColumn.RectTransform)) { ScrollBarVisible = true }; var searchTitle = new GUITextBlock(new RectTransform(new Vector2(0.001f, 1.0f), filterContainer.RectTransform), TextManager.Get("serverlog.filter"), textAlignment: Alignment.CenterLeft, font: GUI.Font); var searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), filterContainer.RectTransform, Anchor.CenterRight), font: GUI.Font); searchBox.OnSelected += (sender, userdata) => { searchTitle.Visible = false; }; searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; }; searchBox.OnTextChanged += (textBox, text) => { FilterSubs(subList, text); return(true); }; var clearButton = new GUIButton(new RectTransform(new Vector2(0.075f, 1.0f), filterContainer.RectTransform), "x") { OnClicked = (btn, userdata) => { searchBox.Text = ""; FilterSubs(subList, ""); searchBox.Flash(Color.White); return(true); } }; if (!isMultiplayer) { subList.OnSelected = OnSubSelected; } // New game right side subPreviewContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.8f), rightColumn.RectTransform)) { Stretch = true }; var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.13f), (isMultiplayer ? leftColumn : rightColumn).RectTransform) { MaxSize = new Point(int.MaxValue, 60) }, childAnchor: Anchor.TopRight); var startButton = new GUIButton(new RectTransform(isMultiplayer ? new Vector2(0.5f, 1.0f) : Vector2.One, buttonContainer.RectTransform, Anchor.BottomRight) { MaxSize = new Point(350, 60) }, TextManager.Get("StartCampaignButton"), style: "GUIButtonLarge") { OnClicked = (GUIButton btn, object userData) => { if (string.IsNullOrWhiteSpace(saveNameBox.Text)) { saveNameBox.Flash(Color.Red); return(false); } if (!(subList.SelectedData is Submarine selectedSub)) { return(false); } if (string.IsNullOrEmpty(selectedSub.MD5Hash.Hash)) { ((GUITextBlock)subList.SelectedComponent).TextColor = Color.DarkRed * 0.8f; subList.SelectedComponent.CanBeFocused = false; subList.Deselect(); return(false); } string savePath = SaveUtil.CreateSavePath(isMultiplayer ? SaveUtil.SaveType.Multiplayer : SaveUtil.SaveType.Singleplayer, saveNameBox.Text); bool hasRequiredContentPackages = selectedSub.RequiredContentPackagesInstalled; if (selectedSub.HasTag(SubmarineTag.Shuttle) || !hasRequiredContentPackages) { if (!hasRequiredContentPackages) { var msgBox = new GUIMessageBox(TextManager.Get("ContentPackageMismatch"), TextManager.GetWithVariable("ContentPackageMismatchWarning", "[requiredcontentpackages]", string.Join(", ", selectedSub.RequiredContentPackages)), new string[] { TextManager.Get("Yes"), TextManager.Get("No") }); msgBox.Buttons[0].OnClicked = msgBox.Close; msgBox.Buttons[0].OnClicked += (button, obj) => { if (GUIMessageBox.MessageBoxes.Count == 0) { StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text); if (isMultiplayer) { CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup"); } } return(true); }; msgBox.Buttons[1].OnClicked = msgBox.Close; } if (selectedSub.HasTag(SubmarineTag.Shuttle)) { var msgBox = new GUIMessageBox(TextManager.Get("ShuttleSelected"), TextManager.Get("ShuttleWarning"), new string[] { TextManager.Get("Yes"), TextManager.Get("No") }); msgBox.Buttons[0].OnClicked = (button, obj) => { StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text); if (isMultiplayer) { CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup"); } return(true); }; msgBox.Buttons[0].OnClicked += msgBox.Close; msgBox.Buttons[1].OnClicked = msgBox.Close; return(false); } } else { StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text); if (isMultiplayer) { CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup"); } } return(true); } }; if (!isMultiplayer) { var disclaimerBtn = new GUIButton(new RectTransform(new Vector2(1.0f, 0.8f), rightColumn.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point(5) }, style: "GUINotificationButton") { IgnoreLayoutGroups = true, OnClicked = (btn, userdata) => { GameMain.Instance.ShowCampaignDisclaimer(); return(true); } }; disclaimerBtn.RectTransform.MaxSize = new Point((int)(30 * GUI.Scale)); } leftColumn.Recalculate(); rightColumn.Recalculate(); UpdateSubList(submarines); UpdateLoadMenu(saveFiles); }
public static string ParseContentPathFromUri(this XObject element) => ToolBox.ConvertAbsoluteToRelativePath(element.BaseUri);
public static void DrawSlot(SpriteBatch spriteBatch, Inventory inventory, InventorySlot slot, Item item, bool drawItem = true) { Rectangle rect = slot.Rect; rect.Location += slot.DrawOffset.ToPoint(); if (slot.HighlightColor.A > 0) { float inflateAmount = (slot.HighlightColor.A / 255.0f) * slot.HighlightScaleUpAmount * 0.5f; rect.Inflate(rect.Width * inflateAmount, rect.Height * inflateAmount); } var itemContainer = item?.GetComponent <ItemContainer>(); if (itemContainer != null && (itemContainer.InventoryTopSprite != null || itemContainer.InventoryBottomSprite != null)) { if (!highlightedSubInventorySlots.Any(s => s.Slot == slot)) { itemContainer.InventoryBottomSprite?.Draw(spriteBatch, new Vector2(rect.Center.X, rect.Y), 0, UIScale); itemContainer.InventoryTopSprite?.Draw(spriteBatch, new Vector2(rect.Center.X, rect.Y), 0, UIScale); } drawItem = false; } else { Sprite slotSprite = slot.SlotSprite ?? slotSpriteSmall; Color slotColor = slot.IsHighlighted ? Color.White : Color.White * 0.8f; if (inventory != null && inventory.Locked) { slotColor = Color.Gray * 0.5f; } spriteBatch.Draw(slotSprite.Texture, rect, slotSprite.SourceRect, slotColor); if (item != null && drawItem) { if (!item.IsFullCondition && (itemContainer == null || !itemContainer.ShowConditionInContainedStateIndicator)) { GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X, rect.Bottom - 8, rect.Width, 8), Color.Black * 0.8f, true); GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X, rect.Bottom - 8, (int)(rect.Width * item.Condition / item.MaxCondition), 8), Color.Lerp(Color.Red, Color.Green, item.Condition / item.MaxCondition) * 0.8f, true); } if (itemContainer != null) { float containedState = 0.0f; if (itemContainer.ShowConditionInContainedStateIndicator) { containedState = item.Condition / item.MaxCondition; } else { containedState = itemContainer.Inventory.Capacity == 1 ? (itemContainer.Inventory.Items[0] == null ? 0.0f : itemContainer.Inventory.Items[0].Condition / itemContainer.Inventory.Items[0].MaxCondition) : itemContainer.Inventory.Items.Count(i => i != null) / (float)itemContainer.Inventory.capacity; } int dir = slot.SubInventoryDir; Rectangle containedIndicatorArea = new Rectangle(rect.X, dir < 0 ? rect.Bottom + HUDLayoutSettings.Padding / 2 : rect.Y - HUDLayoutSettings.Padding / 2 - ContainedIndicatorHeight, rect.Width, ContainedIndicatorHeight); containedIndicatorArea.Inflate(-4, 0); if (itemContainer.ContainedStateIndicator?.Texture == null) { containedIndicatorArea.Inflate(0, -2); GUI.DrawRectangle(spriteBatch, containedIndicatorArea, Color.DarkGray * 0.9f, true); GUI.DrawRectangle(spriteBatch, new Rectangle(containedIndicatorArea.X, containedIndicatorArea.Y, (int)(containedIndicatorArea.Width * containedState), containedIndicatorArea.Height), Color.Lerp(Color.Red, Color.Green, containedState) * 0.8f, true); } else { Sprite indicatorSprite = itemContainer.ContainedStateIndicator; float indicatorScale = Math.Min( containedIndicatorArea.Width / (float)indicatorSprite.SourceRect.Width, containedIndicatorArea.Height / (float)indicatorSprite.SourceRect.Height); if (containedState > 0.0f && containedState < 0.25f) { indicatorScale += ((float)Math.Sin(Timing.TotalTime * 5.0f) + 1.0f) * 0.25f; } indicatorSprite.Draw(spriteBatch, containedIndicatorArea.Center.ToVector2(), (inventory != null && inventory.Locked) ? Color.DarkGray * 0.5f : Color.DarkGray * 0.9f, origin: indicatorSprite.size / 2, rotate: 0.0f, scale: indicatorScale); Color indicatorColor = ToolBox.GradientLerp(containedState, Color.Red, Color.Orange, Color.Green); if (inventory != null && inventory.Locked) { indicatorColor *= 0.5f; } spriteBatch.Draw(indicatorSprite.Texture, containedIndicatorArea.Center.ToVector2(), sourceRectangle: new Rectangle(indicatorSprite.SourceRect.Location, new Point((int)(indicatorSprite.SourceRect.Width * containedState), indicatorSprite.SourceRect.Height)), color: indicatorColor, rotation: 0.0f, origin: indicatorSprite.size / 2, scale: indicatorScale, effects: SpriteEffects.None, layerDepth: 0.0f); } } } } if (GameMain.DebugDraw) { GUI.DrawRectangle(spriteBatch, rect, Color.White, false, 0, 1); GUI.DrawRectangle(spriteBatch, slot.EquipButtonRect, Color.White, false, 0, 1); } if (slot.HighlightColor != Color.Transparent) { GUI.UIGlow.Draw(spriteBatch, rect, slot.HighlightColor); } if (item != null && drawItem) { Sprite sprite = item.Prefab.InventoryIcon ?? item.Sprite; float scale = Math.Min(Math.Min((rect.Width - 10) / sprite.size.X, (rect.Height - 10) / sprite.size.Y), 3.0f); Vector2 itemPos = rect.Center.ToVector2(); if (itemPos.Y > GameMain.GraphicsHeight) { itemPos.Y -= Math.Min( (itemPos.Y + sprite.size.Y / 2 * scale) - GameMain.GraphicsHeight, (itemPos.Y - sprite.size.Y / 2 * scale) - rect.Y); } float rotation = 0.0f; if (slot.HighlightColor.A > 0) { rotation = (float)Math.Sin(slot.HighlightTimer * MathHelper.TwoPi) * slot.HighlightTimer * 0.3f; } Color spriteColor = sprite == item.Sprite ? item.GetSpriteColor() : item.GetInventoryIconColor(); if (inventory != null && inventory.Locked) { spriteColor *= 0.5f; } if (CharacterHealth.OpenHealthWindow != null && !item.UseInHealthInterface) { spriteColor = Color.Lerp(spriteColor, Color.TransparentBlack, 0.5f); } else { sprite.Draw(spriteBatch, itemPos + Vector2.One * 2, Color.Black * 0.6f, rotate: rotation, scale: scale); } sprite.Draw(spriteBatch, itemPos, spriteColor, rotation, scale); } if (inventory != null && !inventory.Locked && Character.Controlled?.Inventory == inventory && slot.QuickUseKey != Keys.None) { GUI.DrawString(spriteBatch, rect.Location.ToVector2(), slot.QuickUseKey.ToString().Substring(1, 1), item == null || !drawItem ? Color.Gray : Color.White, Color.Black * 0.8f); } }
public void StartRound(Level level) { if (isClient) { return; } pendingEventSets.Clear(); selectedEvents.Clear(); activeEvents.Clear(); pathFinder = new PathFinder(WayPoint.WayPointList, indoorsSteering: false); totalPathLength = 0.0f; if (level != null) { var steeringPath = pathFinder.FindPath(ConvertUnits.ToSimUnits(Level.Loaded.StartPosition), ConvertUnits.ToSimUnits(Level.Loaded.EndPosition)); totalPathLength = steeringPath.TotalLength; } this.level = level; SelectSettings(); var initialEventSet = SelectRandomEvents(EventSet.List); if (initialEventSet != null) { pendingEventSets.Add(initialEventSet); int seed = ToolBox.StringToInt(level.Seed); foreach (var previousEvent in level.LevelData.EventHistory) { seed ^= ToolBox.StringToInt(previousEvent.Identifier); } MTRandom rand = new MTRandom(seed); CreateEvents(initialEventSet, rand); } if (level?.LevelData?.Type == LevelData.LevelType.Outpost) { 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; } foreach (EventPrefab ep in eventSet.EventPrefabs.Select(e => e.First)) { if (!level.LevelData.NonRepeatableEvents.Contains(ep)) { level.LevelData.NonRepeatableEvents.Add(ep); } } foreach (EventSet childSet in eventSet.ChildSets) { AddChildEvents(childSet); } } } PreloadContent(GetFilesToPreload()); roundDuration = 0.0f; intensityUpdateTimer = 0.0f; CalculateCurrentIntensity(0.0f); currentIntensity = targetIntensity; eventCoolDown = 0.0f; }
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.SelectedContentPackages, ContentType.Wreck).ToList(); nonPlayerFiles.AddRange(ContentPackage.GetFilesOfType(GameMain.Config.SelectedContentPackages, ContentType.Outpost)); nonPlayerFiles.AddRange(ContentPackage.GetFilesOfType(GameMain.Config.SelectedContentPackages, 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"); }
private void CreateEvents(EventSet eventSet, Random rand) { 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) { 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); 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); } } } }
partial void InitProjSpecific(XDocument doc) { if (doc == null) { GraphicsWidth = 1024; GraphicsHeight = 678; MasterServerUrl = ""; SelectedContentPackage = ContentPackage.list.Any() ? ContentPackage.list[0] : new ContentPackage(""); JobNamePreferences = new List <string>(); foreach (JobPrefab job in JobPrefab.List) { JobNamePreferences.Add(job.Name); } return; } XElement graphicsMode = doc.Root.Element("graphicsmode"); GraphicsWidth = ToolBox.GetAttributeInt(graphicsMode, "width", 0); GraphicsHeight = ToolBox.GetAttributeInt(graphicsMode, "height", 0); VSyncEnabled = ToolBox.GetAttributeBool(graphicsMode, "vsync", true); if (GraphicsWidth == 0 || GraphicsHeight == 0) { GraphicsWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width; GraphicsHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height; } //FullScreenEnabled = ToolBox.GetAttributeBool(graphicsMode, "fullscreen", true); var windowModeStr = ToolBox.GetAttributeString(graphicsMode, "displaymode", "Fullscreen"); if (!Enum.TryParse <WindowMode>(windowModeStr, out windowMode)) { windowMode = WindowMode.Fullscreen; } SoundVolume = ToolBox.GetAttributeFloat(doc.Root, "soundvolume", 1.0f); MusicVolume = ToolBox.GetAttributeFloat(doc.Root, "musicvolume", 0.3f); EnableSplashScreen = ToolBox.GetAttributeBool(doc.Root, "enablesplashscreen", true); keyMapping = new KeyOrMouse[Enum.GetNames(typeof(InputType)).Length]; keyMapping[(int)InputType.Up] = new KeyOrMouse(Keys.W); keyMapping[(int)InputType.Down] = new KeyOrMouse(Keys.S); keyMapping[(int)InputType.Left] = new KeyOrMouse(Keys.A); keyMapping[(int)InputType.Right] = new KeyOrMouse(Keys.D); keyMapping[(int)InputType.Run] = new KeyOrMouse(Keys.LeftShift); keyMapping[(int)InputType.Chat] = new KeyOrMouse(Keys.Tab); keyMapping[(int)InputType.CrewOrders] = new KeyOrMouse(Keys.C); keyMapping[(int)InputType.Select] = new KeyOrMouse(Keys.E); keyMapping[(int)InputType.Use] = new KeyOrMouse(0); keyMapping[(int)InputType.Aim] = new KeyOrMouse(1); foreach (XElement subElement in doc.Root.Elements()) { switch (subElement.Name.ToString().ToLowerInvariant()) { case "keymapping": foreach (XAttribute attribute in subElement.Attributes()) { InputType inputType; if (Enum.TryParse(attribute.Name.ToString(), true, out inputType)) { int mouseButton; if (int.TryParse(attribute.Value.ToString(), out mouseButton)) { keyMapping[(int)inputType] = new KeyOrMouse(mouseButton); } else { Keys key; if (Enum.TryParse(attribute.Value.ToString(), true, out key)) { keyMapping[(int)inputType] = new KeyOrMouse(key); } } } } break; case "gameplay": JobNamePreferences = new List <string>(); foreach (XElement ele in subElement.Element("jobpreferences").Elements("job")) { JobNamePreferences.Add(ToolBox.GetAttributeString(ele, "name", "")); } break; } } foreach (InputType inputType in Enum.GetValues(typeof(InputType))) { if (keyMapping[(int)inputType] == null) { DebugConsole.ThrowError("Key binding for the input type \"" + inputType + " not set!"); keyMapping[(int)inputType] = new KeyOrMouse(Keys.D1); } } UnsavedSettings = false; }
protected override void Update(float deltaTime) { if (!Visible) { return; } UpdateChildrenRect(); RepositionChildren(); if (scrollBarNeedsRecalculation) { UpdateScrollBarSize(); } if (FadeElements) { foreach (var(component, _) in childVisible) { float lerp = 0; float y = component.Rect.Y; float contentY = Content.Rect.Y; float height = component.Rect.Height; if (y < Content.Rect.Y) { float distance = (contentY - y) / height; lerp = distance; } float centerY = Content.Rect.Y + Content.Rect.Height / 2.0f; if (y > centerY) { float distance = (y - centerY) / (centerY - height); lerp = distance; } component.Color = component.HoverColor = ToolBox.GradientLerp(lerp, component.DefaultColor, Color.Transparent); component.DisabledColor = ToolBox.GradientLerp(lerp, component.Style.DisabledColor, Color.Transparent); component.HoverColor = ToolBox.GradientLerp(lerp, component.Style.HoverColor, Color.Transparent); foreach (var child in component.GetAllChildren()) { Color gradient = ToolBox.GradientLerp(lerp, child.DefaultColor, Color.Transparent); child.Color = child.HoverColor = gradient; if (child is GUITextBlock block) { block.TextColor = block.HoverTextColor = gradient; } } } } if (SmoothScroll) { if (targetScroll > -1) { float distance = Math.Abs(targetScroll - BarScroll); float speed = Math.Max(distance * BarSize, 0.1f); BarScroll = (1.0f - speed) * BarScroll + speed * targetScroll; if (MathUtils.NearlyEqual(BarScroll, targetScroll) || GUIScrollBar.DraggingBar != null) { targetScroll = -1; pendingScroll = null; } } } if ((GUI.IsMouseOn(this) || GUI.IsMouseOn(ScrollBar)) && AllowMouseWheelScroll && PlayerInput.ScrollWheelSpeed != 0) { float speed = PlayerInput.ScrollWheelSpeed / 500.0f * BarSize; if (SmoothScroll) { if (ClampScrollToElements) { bool scrollDown = Math.Clamp(PlayerInput.ScrollWheelSpeed, 0, 1) > 0; if (scrollDown) { SelectPrevious(takeKeyBoardFocus: true); } else { SelectNext(takeKeyBoardFocus: true); } } else { pendingScroll = null; if (targetScroll < 0) { targetScroll = BarScroll; } targetScroll -= speed; targetScroll = Math.Clamp(targetScroll, ScrollBar.MinValue, ScrollBar.MaxValue); } } else { ScrollBar.BarScroll -= (PlayerInput.ScrollWheelSpeed / 500.0f) * BarSize; } } ScrollBar.Enabled = ScrollBarEnabled && BarSize < 1.0f; if (AutoHideScrollBar) { ScrollBarVisible = ScrollBar.Enabled; } if (dimensionsNeedsRecalculation) { UpdateDimensions(); } }
public LevelEditorScreen() { cam = new Camera() { MinZoom = 0.01f, MaxZoom = 1.0f }; leftPanel = new GUIFrame(new RectTransform(new Vector2(0.07f, 0.8f), Frame.RectTransform) { MinSize = new Point(150, 0) }, style: "GUIFrameLeft"); 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), "Create Level Object") { OnClicked = (btn, obj) => { Wizard.Instance.Create(); return(true); } }; lightingEnabled = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.025f), paddedLeftPanel.RectTransform), TextManager.Get("LevelEditorLightingEnabled")); cursorLightEnabled = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.025f), paddedLeftPanel.RectTransform), TextManager.Get("LevelEditorCursorLightEnabled")); new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedLeftPanel.RectTransform), TextManager.Get("LevelEditorReloadTextures")) { OnClicked = (btn, obj) => { Level.Loaded?.ReloadTextures(); return(true); } }; new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedLeftPanel.RectTransform), TextManager.Get("LevelEditorSaveAll")) { 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) }, style: "GUIFrameRight"); 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("LevelEditorLevelSeed")); 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("LevelEditorGenerate")) { 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 ? Color.LightGreen : param.Style.textColor; } seedBox.Deselect(); return(true); } }; bottomPanel = new GUIFrame(new RectTransform(new Vector2(0.75f, 0.2f), 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("LevelEditorSpriteEditDone")) { 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 SetTextPos() { if (text == null) { return; } censoredText = string.IsNullOrEmpty(text) ? "" : new string('\u2022', text.Length); var rect = Rect; overflowClipActive = false; wrappedText = text; TextSize = MeasureText(text); if (Wrap && rect.Width > 0) { wrappedText = ToolBox.WrapText(text, rect.Width - padding.X - padding.Z, Font, textScale, playerInput); TextSize = MeasureText(wrappedText); } else if (OverflowClip) { overflowClipActive = TextSize.X > rect.Width - padding.X - padding.Z; } Vector2 minSize = new Vector2( Math.Max(rect.Width - padding.X - padding.Z, 5.0f), Math.Max(rect.Height - padding.Y - padding.W, 5.0f)); if (!autoScaleHorizontal) { minSize.X = float.MaxValue; } if (!Wrap && !autoScaleVertical) { minSize.Y = float.MaxValue; } if ((autoScaleHorizontal || autoScaleVertical) && textScale > 0.1f && (TextSize.X * textScale > minSize.X || TextSize.Y * textScale > minSize.Y)) { TextScale = Math.Max(0.1f, Math.Min(minSize.X / TextSize.X, minSize.Y / TextSize.Y)) - 0.01f; return; } textPos = new Vector2(padding.X + (rect.Width - padding.Z - padding.X) / 2.0f, padding.Y + (rect.Height - padding.Y - padding.W) / 2.0f); origin = TextSize * 0.5f; if (textAlignment.HasFlag(Alignment.Left) && !overflowClipActive) { textPos.X = padding.X; origin.X = 0; } if (textAlignment.HasFlag(Alignment.Right) || overflowClipActive) { textPos.X = rect.Width - padding.Z; origin.X = TextSize.X; } if (textAlignment.HasFlag(Alignment.Top)) { textPos.Y = padding.Y; origin.Y = 0; } if (textAlignment.HasFlag(Alignment.Bottom)) { textPos.Y = rect.Height - padding.W; origin.Y = TextSize.Y; } origin.X = (int)(origin.X); origin.Y = (int)(origin.Y); textPos.X = (int)textPos.X; textPos.Y = (int)textPos.Y; }
public override string ToDebugString() { return($"{ToolBox.GetDebugSymbol(isFinished)} {nameof(NPCFollowAction)} -> (NPCTag: {NPCTag.ColorizeObject()}, TargetTag: {TargetTag.ColorizeObject()}, Follow: {Follow.ColorizeObject()})"); }
private void CreateEvents() { //don't create new events if docked to the start oupost if (Level.Loaded?.StartOutpost != null && Submarine.MainSub.DockedTo.Contains(Level.Loaded.StartOutpost)) { return; } for (int i = selectedEventSets.Count - 1; i >= 0; i--) { ScriptedEventSet eventSet = selectedEventSets[i]; float distFromStart = Vector2.Distance(Submarine.MainSub.WorldPosition, level.StartPosition); float distFromEnd = Vector2.Distance(Submarine.MainSub.WorldPosition, level.EndPosition); float distanceTraveled = MathHelper.Clamp( (Submarine.MainSub.WorldPosition.X - level.StartPosition.X) / (level.EndPosition.X - level.StartPosition.X), 0.0f, 1.0f); //don't create new events if within 50 meters of the start/end of the level if (distanceTraveled <= 0.0f || distFromStart * Physics.DisplayToRealWorldRatio < 50.0f || distFromEnd * Physics.DisplayToRealWorldRatio < 50.0f) { continue; } if ((Submarine.MainSub == null || distanceTraveled < eventSet.MinDistanceTraveled) && roundDuration < eventSet.MinMissionTime) { continue; } if (CurrentIntensity < eventSet.MinIntensity || CurrentIntensity > eventSet.MaxIntensity) { continue; } selectedEventSets.RemoveAt(i); if (eventSet.ChooseRandom) { if (eventSet.EventPrefabs.Count > 0) { MTRandom rand = new MTRandom(ToolBox.StringToInt(level.Seed)); var eventPrefab = ToolBox.SelectWeightedRandom(eventSet.EventPrefabs, eventSet.EventPrefabs.Select(e => e.Commonness).ToList(), rand); if (eventPrefab != null) { var newEvent = eventPrefab.CreateInstance(); newEvent.Init(true); DebugConsole.Log("Initialized event " + newEvent.ToString()); events.Add(newEvent); } } if (eventSet.ChildSets.Count > 0) { var newEventSet = SelectRandomEvents(eventSet.ChildSets); if (newEventSet != null) { selectedEventSets.Add(newEventSet); } } } else { foreach (ScriptedEventPrefab eventPrefab in eventSet.EventPrefabs) { var newEvent = eventPrefab.CreateInstance(); newEvent.Init(true); DebugConsole.Log("Initialized event " + newEvent.ToString()); events.Add(newEvent); } selectedEventSets.AddRange(eventSet.ChildSets); } } }
public void RandomizeSeed() { seedBox.Text = ToolBox.RandomSeed(8); }
public override string ToDebugString() { return($"{ToolBox.GetDebugSymbol(isFinished)} {nameof(ReputationAction)} -> (FactionIdentifier: {Identifier.ColorizeObject()}, TargetType: {TargetType.ColorizeObject()}, Increase: {Increase.ColorizeObject()})"); }
private void Start(GameServer server, int traitorCount) { if (server == null) { return; } List <Character> characters = new List <Character>(); //ANYONE can be a target. List <Character> traitorCandidates = new List <Character>(); //Keep this to not re-pick traitors twice foreach (Client client in server.ConnectedClients) { if (client.Character != null) { characters.Add(client.Character); traitorCandidates.Add(client.Character); } } if (server.Character != null) { characters.Add(server.Character); //Add host character traitorCandidates.Add(server.Character); } if (characters.Count < 2) { return; } codeWords = ToolBox.GetRandomLine(wordsTxt) + ", " + ToolBox.GetRandomLine(wordsTxt); codeResponse = ToolBox.GetRandomLine(wordsTxt) + ", " + ToolBox.GetRandomLine(wordsTxt); while (traitorCount-- > 0) { if (traitorCandidates.Count <= 0) { break; } int traitorIndex = Rand.Int(traitorCandidates.Count); Character traitorCharacter = traitorCandidates[traitorIndex]; traitorCandidates.Remove(traitorCharacter); //Add them to the list traitorList.Add(new Traitor(traitorCharacter)); } //Now that traitors have been decided, let's do objectives in post for deciding things like Document Exchange. foreach (Traitor traitor in traitorList) { Character traitorCharacter = traitor.Character; int targetIndex = Rand.Int(characters.Count); while (characters[targetIndex] == traitorCharacter) //Cannot target self { targetIndex = Rand.Int(characters.Count); } Character targetCharacter = characters[targetIndex]; traitor.TargetCharacter = targetCharacter; traitor.Greet(server, codeWords, codeResponse); } }
private void ProgressWorld() { foreach (Location location in Locations) { if (furthestDiscoveredLocation == null || location.MapPosition.X > furthestDiscoveredLocation.MapPosition.X) { furthestDiscoveredLocation = location; } } foreach (Location location in Locations) { if (location.MapPosition.X < furthestDiscoveredLocation.MapPosition.X) { furthestDiscoveredLocation = location; } if (location == CurrentLocation || location == SelectedLocation) { continue; } //find which types of locations this one can change to var cct = location.Type.CanChangeTo; List <LocationTypeChange> allowedTypeChanges = new List <LocationTypeChange>(); List <int> readyTypeChanges = new List <int>(); for (int i = 0; i < cct.Count; i++) { LocationTypeChange typeChange = cct[i]; if (typeChange.RequireDiscovered && !location.Discovered) { continue; } //check if there are any adjacent locations that would prevent the change bool disallowedFound = false; foreach (string disallowedLocationName in typeChange.DisallowedAdjacentLocations) { if (location.Connections.Any(c => c.OtherLocation(location).Type.Identifier.Equals(disallowedLocationName, StringComparison.OrdinalIgnoreCase))) { disallowedFound = true; break; } } if (disallowedFound) { continue; } //check that there's a required adjacent location present bool requiredFound = false; foreach (string requiredLocationName in typeChange.RequiredAdjacentLocations) { if (location.Connections.Any(c => c.OtherLocation(location).Type.Identifier.Equals(requiredLocationName, StringComparison.OrdinalIgnoreCase))) { requiredFound = true; break; } } if (!requiredFound && typeChange.RequiredAdjacentLocations.Count > 0) { continue; } allowedTypeChanges.Add(typeChange); if (location.TypeChangeTimer >= typeChange.RequiredDuration) { readyTypeChanges.Add(i); } } List <float> readyTypeProbabilities = readyTypeChanges.Select(i => cct[i].DetermineProbability(location)).ToList(); //select a random type change if (Rand.Range(0.0f, 1.0f) < readyTypeChanges.Sum(i => readyTypeProbabilities[i])) { var selectedTypeChangeIndex = ToolBox.SelectWeightedRandom( readyTypeChanges, readyTypeChanges.Select(i => readyTypeProbabilities[i]).ToList(), Rand.RandSync.Unsynced); var selectedTypeChange = cct[selectedTypeChangeIndex]; if (selectedTypeChange != null) { string prevName = location.Name; location.ChangeType(LocationType.List.Find(lt => lt.Identifier.Equals(selectedTypeChange.ChangeToType, StringComparison.OrdinalIgnoreCase))); ChangeLocationType(location, prevName, selectedTypeChange); location.TypeChangeTimer = -1; } } if (allowedTypeChanges.Count > 0) { location.TypeChangeTimer++; } else { location.TypeChangeTimer = 0; } location.UpdateStore(); } }
public override void Update(float deltaTime) { if (disallowed) { Finished(); return; } if (isFinished) { return; } if (spawnPos == null) { if (maxAmountPerLevel < int.MaxValue) { if (Character.CharacterList.Count(c => c.SpeciesName == speciesName) >= maxAmountPerLevel) { disallowed = true; return; } } FindSpawnPosition(affectSubImmediately: true); //the event gets marked as finished if a spawn point is not found if (isFinished) { return; } spawnPending = true; } bool spawnReady = false; if (spawnPending) { //wait until there are no submarines at the spawnpos if (spawnPosType.HasFlag(Level.PositionType.MainPath) || spawnPosType.HasFlag(Level.PositionType.SidePath) || spawnPosType.HasFlag(Level.PositionType.Abyss)) { foreach (Submarine submarine in Submarine.Loaded) { if (submarine.Info.Type != SubmarineType.Player) { continue; } float minDist = GetMinDistanceToSub(submarine); if (Vector2.DistanceSquared(submarine.WorldPosition, spawnPos.Value) < minDist * minDist) { return; } } } //if spawning in a ruin/cave, wait for someone to be close to it to spawning //unnecessary monsters in places the players might never visit during the round if (spawnPosType.HasFlag(Level.PositionType.Ruin) || spawnPosType.HasFlag(Level.PositionType.Cave) || spawnPosType.HasFlag(Level.PositionType.Wreck)) { bool someoneNearby = false; float minDist = Sonar.DefaultSonarRange * 0.8f; foreach (Submarine submarine in Submarine.Loaded) { if (submarine.Info.Type != SubmarineType.Player) { continue; } if (Vector2.DistanceSquared(submarine.WorldPosition, spawnPos.Value) < minDist * minDist) { someoneNearby = true; break; } } foreach (Character c in Character.CharacterList) { if (c == Character.Controlled || c.IsRemotePlayer) { if (Vector2.DistanceSquared(c.WorldPosition, spawnPos.Value) < minDist * minDist) { someoneNearby = true; break; } } } if (!someoneNearby) { return; } } if (spawnPosType.HasFlag(Level.PositionType.Abyss) || spawnPosType.HasFlag(Level.PositionType.AbyssCave)) { bool anyInAbyss = false; foreach (Submarine submarine in Submarine.Loaded) { if (submarine.Info.Type != SubmarineType.Player || submarine == GameMain.NetworkMember?.RespawnManager?.RespawnShuttle) { continue; } if (submarine.WorldPosition.Y < 0) { anyInAbyss = true; break; } } if (!anyInAbyss) { return; } } spawnPending = false; //+1 because Range returns an integer less than the max value int amount = Rand.Range(minAmount, maxAmount + 1); monsters = new List <Character>(); float scatterAmount = scatter; if (spawnPosType.HasFlag(Level.PositionType.SidePath)) { var sidePaths = Level.Loaded.Tunnels.Where(t => t.Type == Level.TunnelType.SidePath); if (sidePaths.Any()) { scatterAmount = Math.Min(scatter, sidePaths.Min(t => t.MinWidth) / 2); } else { scatterAmount = scatter; } } else if (!spawnPosType.HasFlag(Level.PositionType.MainPath)) { scatterAmount = 0; } for (int i = 0; i < amount; i++) { string seed = Level.Loaded.Seed + i.ToString(); CoroutineManager.InvokeAfter(() => { //round ended before the coroutine finished if (GameMain.GameSession == null || Level.Loaded == null) { return; } System.Diagnostics.Debug.Assert(GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer, "Clients should not create monster events."); Vector2 pos = spawnPos.Value + Rand.Vector(scatterAmount); if (scatterAmount > 0) { if (Submarine.Loaded.Any(s => ToolBox.GetWorldBounds(s.Borders.Center, s.Borders.Size).ContainsWorld(pos))) { // Can't use the offset position, let's use the exact spawn position. pos = spawnPos.Value; } else if (Level.Loaded.Ruins.Any(r => ToolBox.GetWorldBounds(r.Area.Center, r.Area.Size).ContainsWorld(pos))) { // Can't use the offset position, let's use the exact spawn position. pos = spawnPos.Value; } } Character createdCharacter = Character.Create(speciesName, pos, seed, characterInfo: null, isRemotePlayer: false, hasAi: true, createNetworkEvent: true); if (GameMain.GameSession.IsCurrentLocationRadiated()) { AfflictionPrefab radiationPrefab = AfflictionPrefab.RadiationSickness; Affliction affliction = new Affliction(radiationPrefab, radiationPrefab.MaxStrength); createdCharacter?.CharacterHealth.ApplyAffliction(null, affliction); // TODO test multiplayer createdCharacter?.Kill(CauseOfDeathType.Affliction, affliction, log: false); } monsters.Add(createdCharacter); if (monsters.Count == amount) { spawnReady = true; //this will do nothing if the monsters have no swarm behavior defined, //otherwise it'll make the spawned characters act as a swarm SwarmBehavior.CreateSwarm(monsters.Cast <AICharacter>()); } }, Rand.Range(0f, amount / 2f)); } } if (!spawnReady) { return; } Entity targetEntity = Submarine.FindClosest(GameMain.GameScreen.Cam.WorldViewCenter); #if CLIENT if (Character.Controlled != null) { targetEntity = Character.Controlled; } #endif bool monstersDead = true; foreach (Character monster in monsters) { if (!monster.IsDead) { monstersDead = false; if (targetEntity != null && Vector2.DistanceSquared(monster.WorldPosition, targetEntity.WorldPosition) < 5000.0f * 5000.0f) { break; } } } if (monstersDead) { Finished(); } }
/// <summary> /// Load a previously saved campaign map from XML /// </summary> private Map(CampaignMode campaign, XElement element) : this() { Seed = element.GetAttributeString("seed", "a"); Rand.SetSyncedSeed(ToolBox.StringToInt(Seed)); foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString().ToLowerInvariant()) { case "location": int i = subElement.GetAttributeInt("i", 0); while (Locations.Count <= i) { Locations.Add(null); } Locations[i] = new Location(subElement); break; } } System.Diagnostics.Debug.Assert(!Locations.Contains(null)); for (int i = 0; i < Locations.Count; i++) { Locations[i].Reputation ??= new Reputation(campaign.CampaignMetadata, $"location.{i}", -100, 100, Rand.Range(-10, 10, Rand.RandSync.Server)); } foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString().ToLowerInvariant()) { case "connection": Point locationIndices = subElement.GetAttributePoint("locations", new Point(0, 1)); var connection = new LocationConnection(Locations[locationIndices.X], Locations[locationIndices.Y]) { Passed = subElement.GetAttributeBool("passed", false), Difficulty = subElement.GetAttributeFloat("difficulty", 0.0f) }; Locations[locationIndices.X].Connections.Add(connection); Locations[locationIndices.Y].Connections.Add(connection); connection.LevelData = new LevelData(subElement.Element("Level")); string biomeId = subElement.GetAttributeString("biome", ""); connection.Biome = LevelGenerationParams.GetBiomes().FirstOrDefault(b => b.Identifier == biomeId) ?? LevelGenerationParams.GetBiomes().FirstOrDefault(b => b.OldIdentifier == biomeId) ?? LevelGenerationParams.GetBiomes().First(); Connections.Add(connection); break; } } int startLocationindex = element.GetAttributeInt("startlocation", -1); if (startLocationindex > 0 && startLocationindex < Locations.Count) { StartLocation = Locations[startLocationindex]; } else { DebugConsole.AddWarning($"Error while loading the map. Start location index out of bounds (index: {startLocationindex}, location count: {Locations.Count})."); foreach (Location location in Locations) { if (!location.Type.HasOutpost) { continue; } if (StartLocation == null || location.MapPosition.X < StartLocation.MapPosition.X) { StartLocation = location; } } } int endLocationindex = element.GetAttributeInt("endlocation", -1); if (endLocationindex > 0 && endLocationindex < Locations.Count) { EndLocation = Locations[endLocationindex]; } else { DebugConsole.AddWarning($"Error while loading the map. End location index out of bounds (index: {endLocationindex}, location count: {Locations.Count})."); foreach (Location location in Locations) { if (EndLocation == null || location.MapPosition.X > EndLocation.MapPosition.X) { EndLocation = location; } } } InitProjectSpecific(); }
private void CreateCharacterElement(CharacterInfo characterInfo, GUIListBox listBox) { GUIFrame frame = new GUIFrame(new RectTransform(new Point(listBox.Content.Rect.Width, GUI.IntScale(45)), listBox.Content.RectTransform), style: "ListBoxElement") { CanBeFocused = false, UserData = characterInfo, Color = (Character.Controlled?.Info == characterInfo) ? TabMenu.OwnCharacterBGColor : Color.Transparent }; var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), frame.RectTransform, Anchor.Center), isHorizontal: true) { AbsoluteSpacing = 2, Stretch = true }; new GUICustomComponent(new RectTransform(new Point(jobColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform, Anchor.Center), onDraw: (sb, component) => characterInfo.DrawJobIcon(sb, component.Rect)) { ToolTip = characterInfo.Job.Name ?? "", HoverColor = Color.White, SelectedColor = Color.White }; GUITextBlock characterNameBlock = new GUITextBlock(new RectTransform(new Point(characterColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform), ToolBox.LimitString(characterInfo.Name, GUI.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: characterInfo.Job.Prefab.UIColor); string statusText = TextManager.Get("StatusOK"); Color statusColor = GUI.Style.Green; Character character = characterInfo.Character; if (character == null || character.IsDead) { if (character == null && characterInfo.IsNewHire && characterInfo.CauseOfDeath == null) { statusText = TextManager.Get("CampaignCrew.NewHire"); statusColor = GUI.Style.Blue; } else if (characterInfo.CauseOfDeath == null) { statusText = TextManager.Get("CauseOfDeathDescription.Unknown"); statusColor = Color.DarkRed; } else if (characterInfo.CauseOfDeath.Type == CauseOfDeathType.Affliction && characterInfo.CauseOfDeath.Affliction == null) { string errorMsg = "Character \"" + characterInfo.Name + "\" had an invalid cause of death (the type of the cause of death was Affliction, but affliction was not specified)."; DebugConsole.ThrowError(errorMsg); GameAnalyticsManager.AddErrorEventOnce("RoundSummary:InvalidCauseOfDeath", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); statusText = TextManager.Get("CauseOfDeathDescription.Unknown"); statusColor = GUI.Style.Red; } else { statusText = characterInfo.CauseOfDeath.Type == CauseOfDeathType.Affliction ? characterInfo.CauseOfDeath.Affliction.CauseOfDeathDescription : TextManager.Get("CauseOfDeathDescription." + characterInfo.CauseOfDeath.Type.ToString()); statusColor = Color.DarkRed; } } else { if (character.IsUnconscious) { statusText = TextManager.Get("Unconscious"); statusColor = Color.DarkOrange; } else if (character.Vitality / character.MaxVitality < 0.8f) { statusText = TextManager.Get("Injured"); statusColor = Color.DarkOrange; } } GUITextBlock statusBlock = new GUITextBlock(new RectTransform(new Point(statusColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform), ToolBox.LimitString(statusText, GUI.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: statusColor); }
public void Generate(bool mirror = false) { if (backgroundSpriteManager == null) { var files = GameMain.SelectedPackage.GetFilesOfType(ContentType.BackgroundSpritePrefabs); if (files.Count > 0) { backgroundSpriteManager = new BackgroundSpriteManager(files); } else { backgroundSpriteManager = new BackgroundSpriteManager("Content/BackgroundSprites/BackgroundSpritePrefabs.xml"); } } #if CLIENT if (backgroundCreatureManager == null) { var files = GameMain.SelectedPackage.GetFilesOfType(ContentType.BackgroundCreaturePrefabs); if (files.Count > 0) { backgroundCreatureManager = new BackgroundCreatureManager(files); } else { backgroundCreatureManager = new BackgroundCreatureManager("Content/BackgroundSprites/BackgroundCreaturePrefabs.xml"); } } #endif Stopwatch sw = new Stopwatch(); sw.Start(); if (loaded != null) { loaded.Unload(); } loaded = this; positionsOfInterest = new List <InterestingPosition>(); Voronoi voronoi = new Voronoi(1.0); List <Vector2> sites = new List <Vector2>(); bodies = new List <Body>(); Rand.SetSyncedSeed(ToolBox.StringToInt(seed)); #if CLIENT renderer = new LevelRenderer(this); backgroundColor = generationParams.BackgroundColor; float avgValue = (backgroundColor.R + backgroundColor.G + backgroundColor.G) / 3; GameMain.LightManager.AmbientLight = new Color(backgroundColor * (10.0f / avgValue), 1.0f); #endif SeaFloorTopPos = generationParams.SeaFloorDepth + generationParams.MountainHeightMax + generationParams.SeaFloorVariance; float minWidth = 6500.0f; if (Submarine.MainSub != null) { Rectangle dockedSubBorders = Submarine.MainSub.GetDockedBorders(); minWidth = Math.Max(minWidth, Math.Max(dockedSubBorders.Width, dockedSubBorders.Height)); } Rectangle pathBorders = borders; pathBorders.Inflate(-minWidth * 2, -minWidth * 2); startPosition = new Vector2( Rand.Range(minWidth, minWidth * 2, Rand.RandSync.Server), Rand.Range(borders.Height * 0.5f, borders.Height - minWidth * 2, Rand.RandSync.Server)); endPosition = new Vector2( borders.Width - Rand.Range(minWidth, minWidth * 2, Rand.RandSync.Server), Rand.Range(borders.Height * 0.5f, borders.Height - minWidth * 2, Rand.RandSync.Server)); //---------------------------------------------------------------------------------- //generate the initial nodes for the main path and smaller tunnels //---------------------------------------------------------------------------------- List <Vector2> pathNodes = new List <Vector2>(); pathNodes.Add(new Vector2(startPosition.X, borders.Height)); Vector2 nodeInterval = generationParams.MainPathNodeIntervalRange; for (float x = startPosition.X + Rand.Range(nodeInterval.X, nodeInterval.Y, Rand.RandSync.Server); x < endPosition.X - Rand.Range(nodeInterval.X, nodeInterval.Y, Rand.RandSync.Server); x += Rand.Range(nodeInterval.X, nodeInterval.Y, Rand.RandSync.Server)) { pathNodes.Add(new Vector2(x, Rand.Range(pathBorders.Y, pathBorders.Bottom, Rand.RandSync.Server))); } pathNodes.Add(new Vector2(endPosition.X, borders.Height)); if (pathNodes.Count <= 2) { pathNodes.Add((startPosition + endPosition) / 2); } GenerateTunnels(pathNodes, minWidth); //---------------------------------------------------------------------------------- //generate voronoi sites //---------------------------------------------------------------------------------- Vector2 siteInterval = generationParams.VoronoiSiteInterval; Vector2 siteVariance = generationParams.VoronoiSiteVariance; for (float x = siteInterval.X / 2; x < borders.Width; x += siteInterval.X) { for (float y = siteInterval.Y / 2; y < borders.Height; y += siteInterval.Y) { Vector2 site = new Vector2( x + Rand.Range(-siteVariance.X, siteVariance.X, Rand.RandSync.Server), y + Rand.Range(-siteVariance.Y, siteVariance.Y, Rand.RandSync.Server)); if (smallTunnels.Any(t => t.Any(node => Vector2.Distance(node, site) < siteInterval.Length()))) { //add some more sites around the small tunnels to generate more small voronoi cells if (x < borders.Width - siteInterval.X) { sites.Add(new Vector2(x, y) + Vector2.UnitX * siteInterval * 0.5f); } if (y < borders.Height - siteInterval.Y) { sites.Add(new Vector2(x, y) + Vector2.UnitY * siteInterval * 0.5f); } if (x < borders.Width - siteInterval.X && y < borders.Height - siteInterval.Y) { sites.Add(new Vector2(x, y) + Vector2.One * siteInterval * 0.5f); } } if (mirror) { site.X = borders.Width - site.X; } sites.Add(site); } } //---------------------------------------------------------------------------------- // construct the voronoi graph and cells //---------------------------------------------------------------------------------- Stopwatch sw2 = new Stopwatch(); sw2.Start(); List <GraphEdge> graphEdges = voronoi.MakeVoronoiGraph(sites, borders.Width, borders.Height); Debug.WriteLine("MakeVoronoiGraph: " + sw2.ElapsedMilliseconds + " ms"); sw2.Restart(); //construct voronoi cells based on the graph edges cells = CaveGenerator.GraphEdgesToCells(graphEdges, borders, GridCellSize, out cellGrid); Debug.WriteLine("find cells: " + sw2.ElapsedMilliseconds + " ms"); sw2.Restart(); //---------------------------------------------------------------------------------- // generate a path through the initial path nodes //---------------------------------------------------------------------------------- List <VoronoiCell> mainPath = CaveGenerator.GeneratePath(pathNodes, cells, cellGrid, GridCellSize, new Rectangle(pathBorders.X, pathBorders.Y, pathBorders.Width, borders.Height), 0.5f, mirror); for (int i = 2; i < mainPath.Count; i += 3) { positionsOfInterest.Add(new InterestingPosition(mainPath[i].Center, PositionType.MainPath)); } List <VoronoiCell> pathCells = new List <VoronoiCell>(mainPath); //make sure the path is wide enough to pass through EnlargeMainPath(pathCells, minWidth); foreach (InterestingPosition positionOfInterest in positionsOfInterest) { WayPoint wayPoint = new WayPoint(positionOfInterest.Position, SpawnType.Enemy, null); wayPoint.MoveWithLevel = true; } startPosition.X = pathCells[0].Center.X; //---------------------------------------------------------------------------------- // tunnels through the tunnel nodes //---------------------------------------------------------------------------------- foreach (List <Vector2> tunnel in smallTunnels) { if (tunnel.Count < 2) { continue; } //find the cell which the path starts from int startCellIndex = CaveGenerator.FindCellIndex(tunnel[0], cells, cellGrid, GridCellSize, 1); if (startCellIndex < 0) { continue; } //if it wasn't one of the cells in the main path, don't create a tunnel if (cells[startCellIndex].CellType != CellType.Path) { continue; } var newPathCells = CaveGenerator.GeneratePath(tunnel, cells, cellGrid, GridCellSize, pathBorders); positionsOfInterest.Add(new InterestingPosition(tunnel.Last(), PositionType.Cave)); if (tunnel.Count > 4) { positionsOfInterest.Add(new InterestingPosition(tunnel[tunnel.Count / 2], PositionType.Cave)); } pathCells.AddRange(newPathCells); } Debug.WriteLine("path: " + sw2.ElapsedMilliseconds + " ms"); sw2.Restart(); //---------------------------------------------------------------------------------- // remove unnecessary cells and create some holes at the bottom of the level //---------------------------------------------------------------------------------- cells = CleanCells(pathCells); pathCells.AddRange(CreateBottomHoles(generationParams.BottomHoleProbability, new Rectangle( (int)(borders.Width * 0.2f), 0, (int)(borders.Width * 0.6f), (int)(borders.Height * 0.8f)))); foreach (VoronoiCell cell in cells) { if (cell.Center.Y < borders.Height / 2) { continue; } cell.edges.ForEach(e => e.OutsideLevel = true); } //---------------------------------------------------------------------------------- // initialize the cells that are still left and insert them into the cell grid //---------------------------------------------------------------------------------- foreach (VoronoiCell cell in pathCells) { cell.edges.ForEach(e => e.OutsideLevel = false); cell.CellType = CellType.Path; cells.Remove(cell); } for (int x = 0; x < cellGrid.GetLength(0); x++) { for (int y = 0; y < cellGrid.GetLength(1); y++) { cellGrid[x, y].Clear(); } } foreach (VoronoiCell cell in cells) { int x = (int)Math.Floor(cell.Center.X / GridCellSize); int y = (int)Math.Floor(cell.Center.Y / GridCellSize); if (x < 0 || y < 0 || x >= cellGrid.GetLength(0) || y >= cellGrid.GetLength(1)) { continue; } cellGrid[x, y].Add(cell); } //---------------------------------------------------------------------------------- // create some ruins //---------------------------------------------------------------------------------- ruins = new List <Ruin>(); for (int i = 0; i < generationParams.RuinCount; i++) { GenerateRuin(mainPath); } //---------------------------------------------------------------------------------- // generate the bodies and rendered triangles of the cells //---------------------------------------------------------------------------------- startPosition.Y = borders.Height; endPosition.Y = borders.Height; List <VoronoiCell> cellsWithBody = new List <VoronoiCell>(cells); List <Vector2[]> triangles; bodies = CaveGenerator.GeneratePolygons(cellsWithBody, out triangles); #if CLIENT renderer.SetBodyVertices(CaveGenerator.GenerateRenderVerticeList(triangles).ToArray(), generationParams.WallColor); renderer.SetWallVertices(CaveGenerator.GenerateWallShapes(cells), generationParams.WallColor); #endif TopBarrier = BodyFactory.CreateEdge(GameMain.World, ConvertUnits.ToSimUnits(new Vector2(borders.X, 0)), ConvertUnits.ToSimUnits(new Vector2(borders.Right, 0))); TopBarrier.SetTransform(ConvertUnits.ToSimUnits(new Vector2(0.0f, borders.Height)), 0.0f); TopBarrier.BodyType = BodyType.Static; TopBarrier.CollisionCategories = Physics.CollisionLevel; bodies.Add(TopBarrier); GenerateSeaFloor(); backgroundSpriteManager.PlaceSprites(this, generationParams.BackgroundSpriteAmount); #if CLIENT backgroundCreatureManager.SpawnSprites(80); #endif foreach (VoronoiCell cell in cells) { foreach (GraphEdge edge in cell.edges) { edge.cell1 = null; edge.cell2 = null; edge.site1 = null; edge.site2 = null; } } //initialize MapEntities that aren't in any sub (e.g. items inside ruins) MapEntity.MapLoaded(null); Debug.WriteLine("Generatelevel: " + sw2.ElapsedMilliseconds + " ms"); sw2.Restart(); if (mirror) { Vector2 temp = startPosition; startPosition = endPosition; endPosition = temp; } Debug.WriteLine("**********************************************************************************"); Debug.WriteLine("Generated a map with " + sites.Count + " sites in " + sw.ElapsedMilliseconds + " ms"); Debug.WriteLine("Seed: " + seed); Debug.WriteLine("**********************************************************************************"); if (GameSettings.VerboseLogging) { DebugConsole.NewMessage("Generated level with the seed " + seed + " (type: " + generationParams.Name + ")", Color.White); } }
private void QuickStart() { Submarine selectedSub = null; string subName = GameMain.Config.QuickStartSubmarineName; if (!string.IsNullOrEmpty(subName)) { DebugConsole.NewMessage($"Loading the predefined quick start sub \"{subName}\"", Color.White); selectedSub = Submarine.SavedSubmarines.FirstOrDefault(s => s.Name.ToLower() == subName.ToLower()); if (selectedSub == null) { DebugConsole.NewMessage($"Cannot find a sub that matches the name \"{subName}\".", Color.Red); } } if (selectedSub == null) { DebugConsole.NewMessage("Loading a random sub.", Color.White); var subs = Submarine.SavedSubmarines.Where(s => !s.HasTag(SubmarineTag.Shuttle) && !s.HasTag(SubmarineTag.HideInMenus)); selectedSub = subs.ElementAt(Rand.Int(subs.Count())); } var gamesession = new GameSession( selectedSub, "Data/Saves/test.xml", GameModePreset.List.Find(gm => gm.Identifier == "devsandbox"), missionPrefab: null); //(gamesession.GameMode as SinglePlayerCampaign).GenerateMap(ToolBox.RandomSeed(8)); gamesession.StartRound(ToolBox.RandomSeed(8)); GameMain.GameScreen.Select(); string[] jobIdentifiers = new string[] { "captain", "engineer", "mechanic" }; for (int i = 0; i < 3; i++) { var spawnPoint = WayPoint.GetRandom(SpawnType.Human, null, Submarine.MainSub); if (spawnPoint == null) { DebugConsole.ThrowError("No spawnpoints found in the selected submarine. Quickstart failed."); GameMain.MainMenuScreen.Select(); return; } var characterInfo = new CharacterInfo( Character.HumanConfigFile, jobPrefab: JobPrefab.List.Find(j => j.Identifier == jobIdentifiers[i])); if (characterInfo.Job == null) { DebugConsole.ThrowError("Failed to find the job \"" + jobIdentifiers[i] + "\"!"); } var newCharacter = Character.Create(Character.HumanConfigFile, spawnPoint.WorldPosition, ToolBox.RandomSeed(8), characterInfo); newCharacter.GiveJobItems(spawnPoint); gamesession.CrewManager.AddCharacter(newCharacter); Character.Controlled = newCharacter; } }
public static Mission LoadRandom(Location[] locations, string seed, bool requireCorrectLocationType, MissionType missionType, bool isSinglePlayer = false) { return(LoadRandom(locations, new MTRandom(ToolBox.StringToInt(seed)), requireCorrectLocationType, missionType, isSinglePlayer)); }
protected List <Tuple <string, Tuple <Client, Character> > > AssignTraitors(GameServer server, TraitorManager traitorManager, Character.TeamType team) { List <Character> characters = FindCharacters(); #if !ALLOW_SOLO_TRAITOR if (characters.Count < 2) { return(null); } #endif var roleCandidates = new Dictionary <string, HashSet <Tuple <Client, Character> > >(); foreach (var role in Roles) { roleCandidates.Add(role.Key, new HashSet <Tuple <Client, Character> >(FindTraitorCandidates(server, team, role.Value))); if (roleCandidates[role.Key].Count <= 0) { return(null); } } var candidateRoleCounts = new Dictionary <Tuple <Client, Character>, int>(); foreach (var candidateEntry in roleCandidates) { foreach (var candidate in candidateEntry.Value) { candidateRoleCounts[candidate] = candidateRoleCounts.TryGetValue(candidate, out var count) ? count + 1 : 1; } } var unassignedRoles = new List <string>(roleCandidates.Keys); unassignedRoles.Sort((a, b) => roleCandidates[a].Count - roleCandidates[b].Count); var assignedCandidates = new List <Tuple <string, Tuple <Client, Character> > >(); while (unassignedRoles.Count > 0) { var currentRole = unassignedRoles[0]; var availableCandidates = roleCandidates[currentRole].ToList(); if (availableCandidates.Count <= 0) { break; } unassignedRoles.RemoveAt(0); availableCandidates.Sort((a, b) => candidateRoleCounts[b] - candidateRoleCounts[a]); unassignedRoles.Sort((a, b) => roleCandidates[a].Count - roleCandidates[b].Count); int numCandidates = 1; for (int i = 1; i < availableCandidates.Count && candidateRoleCounts[availableCandidates[i]] == candidateRoleCounts[availableCandidates[0]]; ++i) { ++numCandidates; } var selected = ToolBox.SelectWeightedRandom(availableCandidates, availableCandidates.Select(c => Math.Max(c.Item1.RoundsSincePlayedAsTraitor, 0.1f)).ToList(), TraitorManager.Random); assignedCandidates.Add(Tuple.Create(currentRole, selected)); foreach (var candidate in roleCandidates.Values) { candidate.Remove(selected); } } if (unassignedRoles.Count > 0) { return(null); } return(assignedCandidates); }
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); } } }