diff --git a/Barotrauma/BarotraumaClient/ClientCode.projitems b/Barotrauma/BarotraumaClient/ClientCode.projitems index e2df0a544..991ce2d39 100644 --- a/Barotrauma/BarotraumaClient/ClientCode.projitems +++ b/Barotrauma/BarotraumaClient/ClientCode.projitems @@ -188,6 +188,7 @@ + diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs index 8f9276859..bcf133b30 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs @@ -152,6 +152,32 @@ namespace Barotrauma } + if (character.MemLocalState.Count > 120) character.MemLocalState.RemoveRange(0, character.MemLocalState.Count - 120); + character.MemState.Clear(); + } + } + + partial void ImpactProjSpecific(float impact, Body body) + { + float volume = MathHelper.Clamp(impact - 3.0f, 0.5f, 1.0f); + + if (body.UserData is Limb limb && character.Stun <= 0f) + { + if (impact > 3.0f) { PlayImpactSound(limb); } + } + else if (body.UserData is Limb || body == Collider.FarseerBody) + { + if (!character.IsRemotePlayer && impact > ImpactTolerance) + { + SoundPlayer.PlayDamageSound("LimbBlunt", strongestImpact, Collider); + } + } + if (Character.Controlled == character) + { + GameMain.GameScreen.Cam.Shake = Math.Min(Math.Max(strongestImpact, GameMain.GameScreen.Cam.Shake), 3.0f); + } + } + if (character.MemState.Count < 1) return; overrideTargetMovement = Vector2.Zero; diff --git a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs index 34cc2ebeb..a82be27e8 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs @@ -86,7 +86,7 @@ namespace Barotrauma if (character.Inventory != null) { if (!character.LockHands && character.Stun < 0.1f && - (character.SelectedConstruction == null || character.SelectedConstruction.GetComponent() == null)) + (character.SelectedConstruction == null || character.SelectedConstruction?.GetComponent()?.User != character)) { character.Inventory.Update(deltaTime, cam); } @@ -321,7 +321,7 @@ namespace Barotrauma } if (character.Inventory != null && !character.LockHands) { - character.Inventory.Locked = (character.SelectedConstruction != null && character.SelectedConstruction.GetComponent() != null); + character.Inventory.Locked = (character.SelectedConstruction?.GetComponent()?.User == character); character.Inventory.DrawOwn(spriteBatch); character.Inventory.CurrentLayout = CharacterHealth.OpenHealthWindow == null && character.SelectedCharacter == null ? CharacterInventory.Layout.Default : diff --git a/Barotrauma/BarotraumaClient/Source/Characters/CharacterInfo.cs b/Barotrauma/BarotraumaClient/Source/Characters/CharacterInfo.cs index e01a3dd2b..473dd6774 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/CharacterInfo.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/CharacterInfo.cs @@ -50,7 +50,7 @@ namespace Barotrauma Job.Name, textColor: Job.Prefab.UIColor, font: font); } - if (personalityTrait != null) + if (personalityTrait != null && TextManager.Language == "English") { new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), headerTextArea.RectTransform), TextManager.Get("PersonalityTrait") + ": " + personalityTrait.Name, font: font); diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Health/CharacterHealth.cs b/Barotrauma/BarotraumaClient/Source/Characters/Health/CharacterHealth.cs index 34ebcb336..8442fe1ba 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/Health/CharacterHealth.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/Health/CharacterHealth.cs @@ -463,7 +463,7 @@ namespace Barotrauma return; } } - + bool forceAfflictionContainerUpdate = false; if (updateDisplayedAfflictionsTimer > 0.0f) { @@ -505,7 +505,7 @@ namespace Barotrauma Math.Min(healthShadowSize + deltaTime, healthBar.BarSize) : Math.Max(healthShadowSize - deltaTime, healthBar.BarSize); } - + dropItemArea.Visible = !Character.IsDead; float blurStrength = 0.0f; @@ -733,7 +733,9 @@ namespace Barotrauma Rectangle.Union(HUDLayoutSettings.AfflictionAreaLeft, HUDLayoutSettings.HealthBarAreaLeft) : Rectangle.Union(HUDLayoutSettings.AfflictionAreaRight, HUDLayoutSettings.HealthBarAreaRight); - if (Character.AllowInput && UseHealthWindow && hoverArea.Contains(PlayerInput.MousePosition) && Inventory.SelectedSlot == null) + if (Character.AllowInput && UseHealthWindow && + Character.SelectedConstruction?.GetComponent()?.User != Character && + hoverArea.Contains(PlayerInput.MousePosition) && Inventory.SelectedSlot == null) { healthBar.State = GUIComponent.ComponentState.Hover; if (PlayerInput.LeftButtonClicked()) diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Jobs/JobPrefab.cs b/Barotrauma/BarotraumaClient/Source/Characters/Jobs/JobPrefab.cs index 1ef7b8cc5..4fc63b3cb 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/Jobs/JobPrefab.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/Jobs/JobPrefab.cs @@ -20,7 +20,7 @@ namespace Barotrauma var skillContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 0.5f), paddedFrame.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.2f + descriptionBlock.RectTransform.RelativeSize.Y) }); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), skillContainer.RectTransform), - TextManager.Get("Skills") + ": ", font: GUI.LargeFont); + TextManager.Get("Skills"), font: GUI.LargeFont); foreach (SkillPrefab skill in Skills) { new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), skillContainer.RectTransform), @@ -30,7 +30,7 @@ namespace Barotrauma var itemContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 0.5f), paddedFrame.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.0f, 0.2f + descriptionBlock.RectTransform.RelativeSize.Y) }); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), itemContainer.RectTransform), - TextManager.Get("Items") + ": ", font: GUI.LargeFont); + TextManager.Get("Items", fallBackTag: "mapentitycategory.equipment"), font: GUI.LargeFont); foreach (string itemName in ItemNames) { new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), itemContainer.RectTransform), diff --git a/Barotrauma/BarotraumaClient/Source/Fonts/ScalableFont.cs b/Barotrauma/BarotraumaClient/Source/Fonts/ScalableFont.cs index 9dd8d9763..2f446ffab 100644 --- a/Barotrauma/BarotraumaClient/Source/Fonts/ScalableFont.cs +++ b/Barotrauma/BarotraumaClient/Source/Fonts/ScalableFont.cs @@ -56,11 +56,11 @@ namespace Barotrauma } public ScalableFont(XElement element, GraphicsDevice gd = null) - : this (element.GetAttributeString("file", ""), (uint)element.GetAttributeInt("size", 14), gd) + : this (element.GetAttributeString("file", ""), (uint)element.GetAttributeInt("size", 14), gd, element.GetAttributeBool("dynamicloading", false)) { } - public ScalableFont(string filename, uint size, GraphicsDevice gd = null) + public ScalableFont(string filename, uint size, GraphicsDevice gd = null, bool dynamicLoading = false) { if (Lib == null) Lib = new Library(); this.filename = filename; @@ -310,6 +310,11 @@ namespace Barotrauma } uint charIndex = text[i]; + if (DynamicLoading && !texCoords.ContainsKey(charIndex)) + { + DynamicRenderAtlas(graphicsDevice, charIndex); + } + if (texCoords.TryGetValue(charIndex, out GlyphData gd) || texCoords.TryGetValue(9633, out gd)) //9633 = white square { if (gd.texIndex >= 0) @@ -344,7 +349,13 @@ namespace Barotrauma currentPos.Y += baseHeight * 1.8f; continue; } - uint charIndex = text[i]; + + uint charIndex = text[i]; + if (DynamicLoading && !texCoords.ContainsKey(charIndex)) + { + DynamicRenderAtlas(graphicsDevice, charIndex); + } + if (texCoords.TryGetValue(charIndex, out GlyphData gd) || texCoords.TryGetValue(9633, out gd)) //9633 = white square { if (gd.texIndex >= 0) @@ -376,6 +387,10 @@ namespace Barotrauma continue; } uint charIndex = text[i]; + if (DynamicLoading && !texCoords.ContainsKey(charIndex)) + { + DynamicRenderAtlas(graphicsDevice, charIndex); + } if (texCoords.TryGetValue(charIndex, out GlyphData gd)) { currentLineX += gd.advance; @@ -389,6 +404,10 @@ namespace Barotrauma { Vector2 retVal = Vector2.Zero; retVal.Y = baseHeight * 1.8f; + if (DynamicLoading && !texCoords.ContainsKey(c)) + { + DynamicRenderAtlas(graphicsDevice, c); + } if (texCoords.TryGetValue(c, out GlyphData gd)) { retVal.X = gd.advance; diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs index e49bb3810..41b769390 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs @@ -166,9 +166,7 @@ namespace Barotrauma get { return enabled; } set { enabled = value; } } - - public bool TileSprites; - + private static GUITextBlock toolTipBlock; public Vector2 Center diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUIStyle.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUIStyle.cs index f54b8d28f..2eddac84f 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/GUIStyle.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/GUIStyle.cs @@ -12,6 +12,10 @@ namespace Barotrauma private XElement configElement; + private GraphicsDevice graphicsDevice; + + private ScalableFont defaultFont; + public ScalableFont Font { get; private set; } public ScalableFont SmallFont { get; private set; } public ScalableFont LargeFont { get; private set; } @@ -83,6 +87,26 @@ namespace Barotrauma } } + /// + /// Returns the default font of the currently selected language + /// + public ScalableFont LoadCurrentDefaultFont() + { + defaultFont?.Dispose(); + defaultFont = null; + foreach (XElement subElement in configElement.Elements()) + { + switch (subElement.Name.ToString().ToLowerInvariant()) + { + case "font": + defaultFont = LoadFont(subElement, graphicsDevice); + break; + } + } + return defaultFont; + } + + private void RescaleFonts() { foreach (XElement subElement in configElement.Elements()) @@ -113,9 +137,10 @@ namespace Barotrauma private ScalableFont LoadFont(XElement element, GraphicsDevice graphicsDevice) { - string file = GetFontFilePath(element); - uint size = GetFontSize(element); - return new ScalableFont(file, size, graphicsDevice); + string file = GetFontFilePath(element); + uint size = GetFontSize(element); + bool dynamicLoading = GetFontDynamicLoading(element); + return new ScalableFont(file, size, graphicsDevice, dynamicLoading); } private uint GetFontSize(XElement element) @@ -146,6 +171,20 @@ namespace Barotrauma return element.GetAttributeString("file", ""); } + private bool GetFontDynamicLoading(XElement element) + { + foreach (XElement subElement in element.Elements()) + { + if (subElement.Name.ToString().ToLowerInvariant() != "override") { continue; } + string language = subElement.GetAttributeString("language", "").ToLowerInvariant(); + if (GameMain.Config.Language.ToLowerInvariant() == language) + { + return subElement.GetAttributeBool("dynamicloading", false); + } + } + return element.GetAttributeBool("dynamicloading", false); + } + public GUIComponentStyle GetComponentStyle(string name) { componentStyles.TryGetValue(name.ToLowerInvariant(), out GUIComponentStyle style); diff --git a/Barotrauma/BarotraumaClient/Source/GUI/LoadingScreen.cs b/Barotrauma/BarotraumaClient/Source/GUI/LoadingScreen.cs index 2ad449123..bcf14a287 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/LoadingScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/LoadingScreen.cs @@ -5,15 +5,19 @@ using System; using System.Collections.Generic; using System.Xml.Linq; using Barotrauma.Media; +using System.Linq; namespace Barotrauma { class LoadingScreen { - private Texture2D backgroundTexture, monsterTexture, titleTexture; + private Texture2D backgroundTexture; private RenderTarget2D renderTarget; + private Sprite languageSelectionCursor; + private ScalableFont languageSelectionFont; + private Video splashScreen; public Video SplashScreen { @@ -37,35 +41,6 @@ namespace Barotrauma private string selectedTip; - public Vector2 CenterPosition; - - public Vector2 TitlePosition; - - private object loadMutex = new object(); - private float? loadState; - - public Vector2 TitleSize - { - get - { - lock (loadMutex) - { - return splashScreen; - } - } - set - { - lock (loadMutex) - { - splashScreen = value; - } - } - } - - private float state; - - private string selectedTip; - public Vector2 BackgroundPosition; public Vector2 TitlePosition; @@ -99,11 +74,17 @@ namespace Barotrauma } public bool WaitForLanguageSelection + { + get; + set; + } + + public LoadingScreen(GraphicsDevice graphics) { backgroundTexture = TextureLoader.FromFile("Content/UI/titleBackground.png"); renderTarget = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight); - GameMain.Instance.OnResolutionChanged += () => + GameMain.Instance.OnResolutionChanged += () => { renderTarget?.Dispose(); renderTarget = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight); @@ -120,7 +101,7 @@ namespace Barotrauma try { DrawSplashScreen(spriteBatch); - if (SplashScreen!=null && SplashScreen.IsPlaying) return; + if (SplashScreen != null && SplashScreen.IsPlaying) return; } catch (Exception e) { @@ -128,20 +109,27 @@ namespace Barotrauma GameMain.Config.EnableSplashScreen = false; } } - + + var titleStyle = GUI.Style?.GetComponentStyle("TitleText"); + Sprite titleSprite = null; + if (!WaitForLanguageSelection && titleStyle != null && titleStyle.Sprites.ContainsKey(GUIComponent.ComponentState.None)) + { + titleSprite = titleStyle.Sprites[GUIComponent.ComponentState.None].First()?.Sprite; + } + drawn = true; graphics.SetRenderTarget(renderTarget); - Scale = GameMain.GraphicsHeight / 1500.0f; + float backgroundScale = GameMain.GraphicsHeight / 1500.0f; + float titleScale = MathHelper.SmoothStep(0.8f, 1.0f, state / 10.0f) * GameMain.GraphicsHeight / 1000.0f; state += deltaTime; if (DrawLoadingText) { - CenterPosition = new Vector2(GameMain.GraphicsWidth * 0.3f, GameMain.GraphicsHeight / 2.0f); - TitlePosition = CenterPosition + new Vector2(-0.0f + (float)Math.Sqrt(state) * 220.0f, 0.0f) * Scale; - TitlePosition.X = Math.Min(TitlePosition.X, (float)GameMain.GraphicsWidth / 2.0f); + BackgroundPosition = new Vector2(GameMain.GraphicsWidth * 0.3f, GameMain.GraphicsHeight * 0.45f); + TitlePosition = new Vector2(GameMain.GraphicsWidth * 0.5f, GameMain.GraphicsHeight * 0.45f); } spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend); @@ -149,16 +137,10 @@ namespace Barotrauma spriteBatch.Draw(backgroundTexture, BackgroundPosition, null, Color.White * Math.Min(state / 5.0f, 1.0f), 0.0f, new Vector2(backgroundTexture.Width / 2.0f, backgroundTexture.Height / 2.0f), - Scale * 1.5f, SpriteEffects.None, 0.2f); - - spriteBatch.Draw(monsterTexture, - CenterPosition + new Vector2((state % 40) * 100.0f - 1800.0f, (state % 40) * 30.0f - 200.0f) * Scale, null, - Color.White, 0.0f, Vector2.Zero, Scale, SpriteEffects.None, 0.1f); - - spriteBatch.Draw(titleTexture, - TitlePosition, null, - Color.White * Math.Min((state - 1.0f) / 5.0f, 1.0f), 0.0f, new Vector2(titleTexture.Width / 2.0f, titleTexture.Height / 2.0f), Scale, SpriteEffects.None, 0.0f); - + backgroundScale * 1.5f, SpriteEffects.None, 0.2f); + + titleSprite?.Draw(spriteBatch, TitlePosition, Color.White * Math.Min((state - 1.0f) / 5.0f, 1.0f), scale: titleScale); + spriteBatch.End(); graphics.SetRenderTarget(null); @@ -171,10 +153,6 @@ namespace Barotrauma spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend); - spriteBatch.Draw(titleTexture, - TitlePosition, null, - Color.White * Math.Min((state - 3.0f) / 5.0f, 1.0f), 0.0f, new Vector2(titleTexture.Width / 2.0f, titleTexture.Height / 2.0f), Scale, SpriteEffects.None, 0.0f); - titleSprite?.Draw(spriteBatch, TitlePosition, Color.White * Math.Min((state - 1.0f) / 5.0f, 1.0f), scale: titleScale); if (WaitForLanguageSelection) @@ -219,6 +197,28 @@ namespace Barotrauma spriteBatch.End(); } + private void DrawLanguageSelectionPrompt(SpriteBatch spriteBatch, GraphicsDevice graphicsDevice) + { + if (languageSelectionFont == null) + { + languageSelectionFont = new ScalableFont("Content/Fonts/BebasNeue-Regular.otf", 28, graphicsDevice); + } + if (languageSelectionCursor == null) + { + languageSelectionCursor = new Sprite("Content/UI/cursor.png", Vector2.Zero); + } + + Vector2 textPos = new Vector2(GameMain.GraphicsWidth / 2, GameMain.GraphicsHeight * 0.25f); + Vector2 textSpacing = new Vector2(0.0f, (GameMain.GraphicsHeight * 0.5f) / TextManager.AvailableLanguages.Count()); + foreach (string language in TextManager.AvailableLanguages) + { + languageSelectionFont.DrawString(spriteBatch, language, textPos - languageSelectionFont.MeasureString(language) / 2, Color.White * 0.8f); + textPos += textSpacing; + } + + languageSelectionCursor.Draw(spriteBatch, PlayerInput.LatestMousePosition); + } + private void DrawSplashScreen(SpriteBatch spriteBatch) { if (SplashScreen != null) diff --git a/Barotrauma/BarotraumaClient/Source/GUI/VideoPlayer.cs b/Barotrauma/BarotraumaClient/Source/GUI/VideoPlayer.cs index ea9adc6f3..be069e5da 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/VideoPlayer.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/VideoPlayer.cs @@ -141,7 +141,7 @@ namespace Barotrauma } currentVideo = CreateVideo(scaledVideoResolution); - title.Text = TextManager.Get(contentId); + title.Text = textSettings != null ? TextManager.Get(contentId) : string.Empty; textContent.Text = textSettings != null ? textSettings.Text : string.Empty; objectiveText.Text = objective; diff --git a/Barotrauma/BarotraumaClient/Source/GameMain.cs b/Barotrauma/BarotraumaClient/Source/GameMain.cs index ef1c7274f..f7b623682 100644 --- a/Barotrauma/BarotraumaClient/Source/GameMain.cs +++ b/Barotrauma/BarotraumaClient/Source/GameMain.cs @@ -178,7 +178,6 @@ namespace Barotrauma GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window); - PerformanceCounter = new PerformanceCounter(); IsFixedTimeStep = false; @@ -322,6 +321,11 @@ namespace Barotrauma DebugConsole.NewMessage("LOADING COROUTINE", Color.Lime); } + while (TitleScreen.WaitForLanguageSelection) + { + yield return CoroutineStatus.Running; + } + SoundManager = new Sounds.SoundManager(); SoundManager.SetCategoryGainMultiplier("default", Config.SoundVolume); SoundManager.SetCategoryGainMultiplier("ui", Config.SoundVolume); @@ -370,11 +374,9 @@ namespace Barotrauma InitUserStats(); yield return CoroutineStatus.Running; - - + LightManager = new Lights.LightManager(base.GraphicsDevice, Content); - WaterRenderer.Instance = new WaterRenderer(base.GraphicsDevice, Content); TitleScreen.LoadState = 1.0f; yield return CoroutineStatus.Running; @@ -525,7 +527,7 @@ namespace Barotrauma protected override void UnloadContent() { Video.Close(); - SoundManager.Dispose(); + SoundManager?.Dispose(); } /// diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs b/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs index e9bd2ba83..8b52b1fd9 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs @@ -74,12 +74,17 @@ namespace Barotrauma public CrewManager(XElement element, bool isSinglePlayer) : this(isSinglePlayer) { - if (!isSinglePlayer) + if (GameMain.Client != null) { - DebugConsole.ThrowError("Cannot add messages to single player chat box in multiplayer mode!\n" + Environment.StackTrace); + //let the server create random conversations in MP return; } - if (string.IsNullOrEmpty(text)) { return; } + List availableSpeakers = Character.CharacterList.FindAll(c => + c.AIController is HumanAIController && + !c.IsDead && + c.SpeechImpediment <= 100.0f); + pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers)); + } var characterInfo = new CharacterInfo(subElement); characterInfos.Add(characterInfo); @@ -90,7 +95,6 @@ namespace Barotrauma break; } } - ChatBox.AddMessage(ChatMessage.Create(senderName, text, messageType, sender)); } partial void InitProjectSpecific() @@ -239,27 +243,24 @@ namespace Barotrauma public IEnumerable GetCharacters() { - if (character?.Inventory == null) return null; + if (characterInfos.Contains(characterInfo)) + { + DebugConsole.ThrowError("Tried to add the same character info to CrewManager twice.\n" + Environment.StackTrace); + return; + } - var radioItem = character.Inventory.Items.FirstOrDefault(it => it != null && it.GetComponent() != null); - if (radioItem == null) return null; - if (requireEquipped && !character.HasEquippedItem(radioItem)) return null; - - return radioItem.GetComponent(); + characterInfos.Add(characterInfo); } public IEnumerable GetCharacterInfos() { - if (GameMain.Client != null) + if (character == null) { - //let the server create random conversations in MP + DebugConsole.ThrowError("Tried to remove a null character from CrewManager.\n" + Environment.StackTrace); return; } - List availableSpeakers = Character.CharacterList.FindAll(c => - c.AIController is HumanAIController && - !c.IsDead && - c.SpeechImpediment <= 100.0f); - pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers)); + characters.Remove(character); + if (removeInfo) characterInfos.Remove(character.Info); } public void AddCharacter(Character character) @@ -633,9 +634,183 @@ namespace Barotrauma { characterListBox.BarScroll = roundedPos; } - soundIcon.Visible = !muted && !mutedLocally; - soundIconDisabled.Visible = muted || mutedLocally; - soundIconDisabled.ToolTip = TextManager.Get(mutedLocally ? "MutedLocally" : "MutedGlobally"); + var characterArea = new GUIButton(new RectTransform(new Point(characterInfoWidth, frame.Rect.Height), frame.RectTransform, Anchor.CenterLeft), style: "GUITextBox") + { + UserData = character, + Color = frame.Color, + SelectedColor = frame.SelectedColor, + HoverColor = frame.HoverColor, + ToolTip = characterToolTip + }; + + var soundIcon = new GUIImage(new RectTransform(new Point((int)(characterArea.Rect.Height * 0.5f)), characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(5, 0) }, + "GUISoundIcon") + { + UserData = "soundicon", + CanBeFocused = false, + Visible = true + }; + soundIcon.Color = new Color(soundIcon.Color, 0.0f); + new GUIImage(new RectTransform(new Point((int)(characterArea.Rect.Height * 0.5f)), characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(5, 0) }, + "GUISoundIconDisabled") + { + UserData = "soundicondisabled", + CanBeFocused = true, + Visible = false + }; + + if (isSinglePlayer) + { + characterArea.OnClicked = CharacterClicked; + } + else + { + characterArea.CanBeFocused = false; + characterArea.CanBeSelected = false; + } + + var characterImage = new GUICustomComponent(new RectTransform(new Point(characterArea.Rect.Height), characterArea.RectTransform, Anchor.CenterLeft), + onDraw: (sb, component) => character.Info.DrawIcon(sb, component.Rect.Center.ToVector2(), targetAreaSize: component.Rect.Size.ToVector2())) + { + CanBeFocused = false, + HoverColor = Color.White, + SelectedColor = Color.White, + ToolTip = characterToolTip + }; + + var characterName = new GUITextBlock(new RectTransform(new Point(characterArea.Rect.Width - characterImage.Rect.Width - soundIcon.Rect.Width - 10, characterArea.Rect.Height), + characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(soundIcon.Rect.Width + 10, 0) }, + character.Name, textColor: frame.Color, font: GUI.SmallFont, wrap: true) + { + Color = frame.Color, + HoverColor = Color.Transparent, + SelectedColor = Color.Transparent, + CanBeFocused = false, + ToolTip = characterToolTip, + AutoScale = true + }; + + //---------------- order buttons ---------------- + + var orderButtonFrame = new GUILayoutGroup(new RectTransform(new Point(100, frame.Rect.Height), frame.RectTransform) + { AbsoluteOffset = new Point(characterInfoWidth + spacing, 0) }, + isHorizontal: true, childAnchor: Anchor.CenterLeft) + { + AbsoluteSpacing = (int)(10 * GUI.Scale), + UserData = "orderbuttons", + CanBeFocused = false + }; + + //listbox for holding the orders inappropriate for this character + //(so we can easily toggle their visibility) + var wrongOrderList = new GUIListBox(new RectTransform(new Point(50, orderButtonFrame.Rect.Height), orderButtonFrame.RectTransform), isHorizontal: true, style: null) + { + ScrollBarEnabled = false, + ScrollBarVisible = false, + Enabled = false, + Spacing = spacing, + ClampMouseRectToParent = false + }; + wrongOrderList.Content.ClampMouseRectToParent = false; + + for (int i = 0; i < orders.Count; i++) + { + var order = orders[i]; + if (order.TargetAllCharacters) continue; + + RectTransform btnParent = (i >= correctOrderCount + neutralOrderCount) ? + wrongOrderList.Content.RectTransform : + orderButtonFrame.RectTransform; + + var btn = new GUIButton(new RectTransform(new Point(iconSize, iconSize), btnParent, Anchor.CenterLeft), + style: null) + { + UserData = order + }; + + new GUIFrame(new RectTransform(new Vector2(1.5f), btn.RectTransform, Anchor.Center), "OuterGlow") + { + Color = Color.Lerp(order.Color, frame.Color, 0.5f) * 0.8f, + HoverColor = Color.Lerp(order.Color, frame.Color, 0.5f) * 1.0f, + PressedColor = Color.Lerp(order.Color, frame.Color, 0.5f) * 0.6f, + UserData = "selected", + CanBeFocused = false, + Visible = false + }; + + var img = new GUIImage(new RectTransform(Vector2.One, btn.RectTransform), order.Prefab.SymbolSprite); + img.Scale = iconSize / (float)img.SourceRect.Width; + img.Color = Color.Lerp(order.Color, frame.Color, 0.5f); + img.ToolTip = order.Name; + img.HoverColor = Color.Lerp(img.Color, Color.White, 0.5f); + + btn.OnClicked += (GUIButton button, object userData) => + { + if (Character.Controlled == null || Character.Controlled.SpeechImpediment >= 100.0f) return false; + + if (btn.GetChildByUserData("selected").Visible) + { + SetCharacterOrder(character, Order.PrefabList.Find(o => o.AITag == "dismissed"), null, Character.Controlled); + } + else + { + if (order.ItemComponentType != null || order.ItemIdentifiers.Length > 0 || order.Options.Length > 1) + { + CreateOrderTargetFrame(button, character, order); + } + else + { + SetCharacterOrder(character, order, null, Character.Controlled); + } + } + return true; + }; + btn.UserData = order; + btn.ToolTip = order.Name; + + //divider between different groups of orders + if (i == correctOrderCount - 1 || i == correctOrderCount + neutralOrderCount - 1) + { + //TODO: divider sprite + new GUIFrame(new RectTransform(new Point(8, iconSize), orderButtonFrame.RectTransform), style: "GUIButton"); + } + } + + var toggleWrongOrderBtn = new GUIButton(new RectTransform(new Point((int)(30 * GUI.Scale), wrongOrderList.Rect.Height), wrongOrderList.Content.RectTransform), + "", style: "UIToggleButton") + { + UserData = "togglewrongorder", + CanBeFocused = false + }; + + wrongOrderList.RectTransform.NonScaledSize = new Point( + wrongOrderList.Content.Children.Sum(c => c.Rect.Width + wrongOrderList.Spacing), + wrongOrderList.RectTransform.NonScaledSize.Y); + wrongOrderList.RectTransform.SetAsLastChild(); + + new GUIFrame(new RectTransform(new Point( + wrongOrderList.Rect.Width - toggleWrongOrderBtn.Rect.Width - wrongOrderList.Spacing * 2, + wrongOrderList.Rect.Height), wrongOrderList.Content.RectTransform), + style: null) + { + CanBeFocused = false + }; + + //scale to fit the content + orderButtonFrame.RectTransform.NonScaledSize = new Point( + orderButtonFrame.Children.Sum(c => c.Rect.Width + orderButtonFrame.AbsoluteSpacing), + orderButtonFrame.RectTransform.NonScaledSize.Y); + + frame.RectTransform.NonScaledSize = new Point( + characterInfoWidth + spacing + (orderButtonFrame.Rect.Width - wrongOrderList.Rect.Width), + frame.RectTransform.NonScaledSize.Y); + + characterListBox.RectTransform.NonScaledSize = new Point( + characterListBox.Content.Children.Max(c => c.Rect.Width) + wrongOrderList.Rect.Width, + characterListBox.RectTransform.NonScaledSize.Y); + characterListBox.Content.RectTransform.NonScaledSize = characterListBox.RectTransform.NonScaledSize; + characterListBox.UpdateScrollBarSize(); + return frame; } private IEnumerable KillCharacterAnim(GUIComponent component) @@ -779,6 +954,12 @@ namespace Barotrauma } return; } + List availableSpeakers = Character.CharacterList.FindAll(c => + c.AIController is HumanAIController && + !c.IsDead && + c.SpeechImpediment <= 100.0f); + pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers)); + } character.SetOrder(order, option, orderGiver, speak: orderGiver != character); if (IsSinglePlayer) @@ -836,19 +1017,23 @@ namespace Barotrauma } } } - //only one target (or an order with no particular targets), just show options - else + + character.SetOrder(order, option, orderGiver, speak: orderGiver != character); + if (IsSinglePlayer) { - orderTargetFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.2f + order.Options.Length * 0.1f, 0.18f), GUI.Canvas) - { AbsoluteOffset = new Point(orderButton.Rect.Center.X, orderButton.Rect.Bottom) }, - isHorizontal: true, childAnchor: Anchor.BottomLeft) + orderGiver?.Speak( + order.GetChatMessage(character.Name, orderGiver.CurrentHull?.DisplayName, givingOrderToSelf: character == orderGiver, orderOption: option), null); + } + else if (orderGiver != null) + { + OrderChatMessage msg = new OrderChatMessage(order, option, order.TargetItemComponent?.Item, character, orderGiver); + if (GameMain.Client != null) { - UserData = character, - Stretch = true - }; - //line connecting the order button to the option buttons - //TODO: sprite - new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), orderTargetFrame.RectTransform), style: null); + GameMain.Client.SendChatMessage(msg); + } + } + DisplayCharacterOrder(character, order); + } /// /// Create the UI panel that's used to select the target and options for a given order diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/Tutorial.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/Tutorial.cs index 5106b9aba..442b34a43 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/Tutorial.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/Tutorial.cs @@ -305,7 +305,7 @@ namespace Barotrauma.Tutorials infoBox = CreateInfoFrame(TextManager.Get(activeContentSegment.Id), tutorialText, activeContentSegment.TextContent.GetAttributeInt("width", 300), activeContentSegment.TextContent.GetAttributeInt("height", 80), - activeContentSegment.TextContent.GetAttributeString("anchor", "Center"), true, StopCurrentContentSegment, () => LoadVideo(activeContentSegment, false)); + activeContentSegment.TextContent.GetAttributeString("anchor", "Center"), true, StopCurrentContentSegment, () => LoadVideo(activeContentSegment)); break; case TutorialContentTypes.TextOnly: infoBox = CreateInfoFrame(TextManager.Get(activeContentSegment.Id), tutorialText, @@ -404,7 +404,8 @@ namespace Barotrauma.Tutorials { if (ContentRunning) return; ContentRunning = true; - videoPlayer.LoadContent(playableContentPath, new VideoPlayer.VideoSettings(segment.VideoContent), new VideoPlayer.TextSettings(segment.VideoContent), segment.Id, true, callback: () => ContentRunning = false); + LoadVideo(segment); + //videoPlayer.LoadContent(playableContentPath, new VideoPlayer.VideoSettings(segment.VideoContent), new VideoPlayer.TextSettings(segment.VideoContent), segment.Id, true, callback: () => ContentRunning = false); } private void ShowSegmentText(TutorialSegment segment) @@ -419,7 +420,7 @@ namespace Barotrauma.Tutorials if (segment.ContentType != TutorialContentTypes.TextOnly) { - videoAction = () => LoadVideo(segment, false); + videoAction = () => LoadVideo(segment); } infoBox = CreateInfoFrame(TextManager.Get(segment.Id), tutorialText, @@ -566,16 +567,16 @@ namespace Barotrauma.Tutorials #endregion #region Video - protected void LoadVideo(TutorialSegment segment, bool showText = true) + protected void LoadVideo(TutorialSegment segment) { if (videoPlayer == null) videoPlayer = new VideoPlayer(); - if (showText) + if (segment.ContentType != TutorialContentTypes.ManualVideo) { videoPlayer.LoadContent(playableContentPath, new VideoPlayer.VideoSettings(segment.VideoContent), new VideoPlayer.TextSettings(segment.VideoContent), segment.Id, true, segment.Objective, StopCurrentContentSegment); } else { - videoPlayer.LoadContent(playableContentPath, new VideoPlayer.VideoSettings(segment.VideoContent), null, segment.Id, true, segment.Objective, null); + videoPlayer.LoadContent(playableContentPath, new VideoPlayer.VideoSettings(segment.VideoContent), null, segment.Id, true, string.Empty, null); } } #endregion diff --git a/Barotrauma/BarotraumaClient/Source/GameSettings.cs b/Barotrauma/BarotraumaClient/Source/GameSettings.cs index 017a3e7e9..79addfd49 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSettings.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSettings.cs @@ -132,19 +132,24 @@ namespace Barotrauma var languageDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.045f), generalLayoutGroup.RectTransform)); foreach (string language in TextManager.AvailableLanguages) { - languageDD.AddItem(TextManager.Get("Language." + language, returnNull: true) ?? language, language); + //TODO: display the name of the language in the target language? + languageDD.AddItem(language, language); } languageDD.SelectItem(TextManager.Language); languageDD.OnSelected = (guiComponent, obj) => { string newLanguage = obj as string; if (newLanguage == Language) return true; - - UnsavedSettings = true; + Language = newLanguage; ApplySettings(); - new GUIMessageBox(TextManager.Get("RestartRequiredLabel"), TextManager.Get("RestartRequiredLanguage")); + var msgBox = new GUIMessageBox(TextManager.Get("RestartRequiredLabel"), TextManager.Get("RestartRequiredLanguage")); + //change fonts to the default font of the new language to make sure + //they can be displayed when for example changing from English to Chinese + var defaultFont = GUI.Style.LoadCurrentDefaultFont(); + msgBox.Header.Font = defaultFont; + msgBox.Text.Font = defaultFont; return true; }; diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Pump.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Pump.cs index 5ef0e010c..8dc301955 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Pump.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Pump.cs @@ -78,8 +78,8 @@ namespace Barotrauma.Items.Components CanBeFocused = false }; - var pumpSpeedText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), rightArea.RectTransform) { RelativeOffset = new Vector2(0.25f, 0.0f) }, - "", textAlignment: Alignment.BottomLeft); + var pumpSpeedText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), rightArea.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.0f) }, + "", textAlignment: Alignment.BottomLeft, wrap: true); string pumpSpeedStr = TextManager.Get("PumpSpeed"); pumpSpeedText.TextGetter = () => { return pumpSpeedStr + ": " + (int)flowPercentage + " %"; }; @@ -90,7 +90,7 @@ namespace Barotrauma.Items.Components }; new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), sliderArea.RectTransform), - TextManager.Get("PumpOut"), textAlignment: Alignment.Center); + TextManager.Get("PumpOut"), textAlignment: Alignment.Center, wrap: true, font: GUI.SmallFont); pumpSpeedSlider = new GUIScrollBar(new RectTransform(new Vector2(0.8f, 1.0f), sliderArea.RectTransform), barSize: 0.25f, style: "GUISlider") { Step = 0.05f, @@ -111,7 +111,7 @@ namespace Barotrauma.Items.Components }; new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), sliderArea.RectTransform), - TextManager.Get("PumpIn"), textAlignment: Alignment.Center); + TextManager.Get("PumpIn"), textAlignment: Alignment.Center, wrap: true, font: GUI.SmallFont); } public override void OnItemLoaded() diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Reactor.cs index 1fc3955ca..4dbe476c3 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Reactor.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Reactor.cs @@ -104,13 +104,13 @@ namespace Barotrauma.Items.Components var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.85f), GuiFrame.RectTransform, Anchor.Center), isHorizontal: true) { - RelativeSpacing = 0.015f, + RelativeSpacing = 0.012f, Stretch = true }; - GUIFrame columnLeft = new GUIFrame(new RectTransform(new Vector2(0.2f, 1.0f), paddedFrame.RectTransform), style: null); + GUIFrame columnLeft = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f), paddedFrame.RectTransform), style: null); leftHUDColumn = columnLeft; - GUIFrame columnMid = new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), paddedFrame.RectTransform), style: null); + GUIFrame columnMid = new GUIFrame(new RectTransform(new Vector2(0.45f, 1.0f), paddedFrame.RectTransform), style: null); GUIFrame columnRight = new GUIFrame(new RectTransform(new Vector2(0.3f, 1.0f), paddedFrame.RectTransform), style: null); //---------------------------------------------------------- @@ -131,7 +131,7 @@ namespace Barotrauma.Items.Components }; var btnText = warningBtn.GetChild(); - btnText.Font = GUI.SmallFont; + btnText.Font = GUI.Font; btnText.Wrap = true; btnText.SetTextPos(); warningButtons.Add(warningTexts[i], warningBtn); diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Signal/CustomInterface.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Signal/CustomInterface.cs index 124992e2c..e3480c50a 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Signal/CustomInterface.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Signal/CustomInterface.cs @@ -117,11 +117,11 @@ namespace Barotrauma.Items.Components { if (uiElements[i] is GUIButton button) { - button.Text = labels[i]; + button.Text = customInterfaceElementList[i].Label; } else if (uiElements[i] is GUITickBox tickBox) { - tickBox.Text = labels[i]; + tickBox.Text = customInterfaceElementList[i].Label; } } } diff --git a/Barotrauma/BarotraumaClient/Source/Items/ItemInventory.cs b/Barotrauma/BarotraumaClient/Source/Items/ItemInventory.cs index 6ef97a119..7483ce030 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/ItemInventory.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/ItemInventory.cs @@ -92,6 +92,7 @@ namespace Barotrauma if (!string.IsNullOrEmpty(uiLabel) && !subInventory) { + uiLabel = ToolBox.WrapText(uiLabel, BackgroundFrame.Width, GUI.Font, 1); GUI.DrawString(spriteBatch, new Vector2((int)(BackgroundFrame.Center.X - GUI.Font.MeasureString(uiLabel).X / 2), (int)BackgroundFrame.Y + 5), uiLabel, Color.White * 0.9f); diff --git a/Barotrauma/BarotraumaClient/Source/Map/Map/Map.cs b/Barotrauma/BarotraumaClient/Source/Map/Map/Map.cs index 45a0a836b..ad7f5a622 100644 --- a/Barotrauma/BarotraumaClient/Source/Map/Map/Map.cs +++ b/Barotrauma/BarotraumaClient/Source/Map/Map/Map.cs @@ -638,7 +638,9 @@ namespace Barotrauma if (mouseOn && PlayerInput.LeftButtonClicked() && !messageBoxOpen) { + //TODO: translate or replace var messageBox = new GUIMessageBox("Mysteries lie ahead...", "This area is unreachable in this version of Barotrauma. Please wait for future updates!"); + messageBoxOpen = true; CoroutineManager.StartCoroutine(WaitForMessageBoxClosed(messageBox)); } } diff --git a/Barotrauma/BarotraumaClient/Source/Map/Submarine.cs b/Barotrauma/BarotraumaClient/Source/Map/Submarine.cs index bcea54eb8..66c925d4c 100644 --- a/Barotrauma/BarotraumaClient/Source/Map/Submarine.cs +++ b/Barotrauma/BarotraumaClient/Source/Map/Submarine.cs @@ -315,7 +315,7 @@ namespace Barotrauma var dimensionsText = new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionBox.Content.RectTransform), TextManager.Get("Dimensions"), textAlignment: Alignment.TopLeft, font: GUI.Font, wrap: true) { CanBeFocused = false }; - new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), dimensionsText.RectTransform, Anchor.TopRight), + new GUITextBlock(new RectTransform(new Vector2(0.45f, 0.0f), dimensionsText.RectTransform, Anchor.TopRight), dimensionsStr, textAlignment: Alignment.TopLeft, font: GUI.Font, wrap: true) { CanBeFocused = false }; dimensionsText.RectTransform.MinSize = new Point(0, dimensionsText.Children.First().Rect.Height); @@ -326,7 +326,7 @@ namespace Barotrauma var crewSizeText = new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionBox.Content.RectTransform), TextManager.Get("RecommendedCrewSize"), textAlignment: Alignment.TopLeft, font: GUI.Font, wrap: true) { CanBeFocused = false }; - new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), crewSizeText.RectTransform, Anchor.TopRight), + new GUITextBlock(new RectTransform(new Vector2(0.45f, 0.0f), crewSizeText.RectTransform, Anchor.TopRight), RecommendedCrewSizeMin + " - " + RecommendedCrewSizeMax, textAlignment: Alignment.TopLeft, font: GUI.Font, wrap: true) { CanBeFocused = false }; crewSizeText.RectTransform.MinSize = new Point(0, crewSizeText.Children.First().Rect.Height); @@ -337,7 +337,7 @@ namespace Barotrauma var crewExperienceText = new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionBox.Content.RectTransform), TextManager.Get("RecommendedCrewExperience"), textAlignment: Alignment.TopLeft, font: GUI.Font, wrap: true) { CanBeFocused = false }; - new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), crewExperienceText.RectTransform, Anchor.TopRight), + new GUITextBlock(new RectTransform(new Vector2(0.45f, 0.0f), crewExperienceText.RectTransform, Anchor.TopRight), TextManager.Get(RecommendedCrewExperience), textAlignment: Alignment.TopLeft, font: GUI.Font, wrap: true) { CanBeFocused = false }; crewExperienceText.RectTransform.MinSize = new Point(0, crewExperienceText.Children.First().Rect.Height); @@ -348,18 +348,21 @@ namespace Barotrauma var contentPackagesText = new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionBox.Content.RectTransform), TextManager.Get("RequiredContentPackages"), textAlignment: Alignment.TopLeft, font: GUI.Font) { CanBeFocused = false }; - new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), contentPackagesText.RectTransform, Anchor.TopRight), + new GUITextBlock(new RectTransform(new Vector2(0.45f, 0.0f), contentPackagesText.RectTransform, Anchor.TopRight), string.Join(", ", RequiredContentPackages), textAlignment: Alignment.TopLeft, font: GUI.Font, wrap: true) { CanBeFocused = false }; contentPackagesText.RectTransform.MinSize = new Point(0, contentPackagesText.Children.First().Rect.Height); } + GUITextBlock.AutoScaleAndNormalize(descriptionBox.Content.Children.Where(c => c is GUITextBlock).Cast()); + //space new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), descriptionBox.Content.RectTransform), style: null); if (Description.Length != 0) { - new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionBox.Content.RectTransform), TextManager.Get("SaveSubDialogDescription") + ":", font: GUI.Font, wrap: true) { CanBeFocused = false, ForceUpperCase = true }; + new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionBox.Content.RectTransform), + TextManager.Get("SaveSubDialogDescription", fallBackTag: "WorkshopItemDescription"), font: GUI.Font, wrap: true) { CanBeFocused = false, ForceUpperCase = true }; } new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionBox.Content.RectTransform), Description, font: GUI.Font, wrap: true) diff --git a/Barotrauma/BarotraumaClient/Source/Program.cs b/Barotrauma/BarotraumaClient/Source/Program.cs index 1fc149762..37646cf3f 100644 --- a/Barotrauma/BarotraumaClient/Source/Program.cs +++ b/Barotrauma/BarotraumaClient/Source/Program.cs @@ -214,6 +214,10 @@ namespace Barotrauma sb.AppendLine("Level seed: " + ((Level.Loaded == null) ? "no level loaded" : Level.Loaded.Seed)); sb.AppendLine("Loaded submarine: " + ((Submarine.MainSub == null) ? "None" : Submarine.MainSub.Name + " (" + Submarine.MainSub.MD5Hash + ")")); sb.AppendLine("Selected screen: " + (Screen.Selected == null ? "None" : Screen.Selected.ToString())); + if (SteamManager.IsInitialized) + { + sb.AppendLine("SteamManager initialized"); + } if (GameMain.Client != null) { diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs b/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs index 2cda021b3..c3a28017c 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs @@ -240,6 +240,8 @@ namespace Barotrauma private GUILayoutGroup subPreviewContainer; + private GUILayoutGroup subPreviewContainer; + private GUIButton loadGameButton; public Action StartNewGame; @@ -509,7 +511,7 @@ namespace Barotrauma { IsFixedSize = false }, - TextManager.Get("Shuttle"), textAlignment: Alignment.Right, font: GUI.SmallFont) + TextManager.Get("Shuttle", fallBackTag: "RespawnShuttle"), textAlignment: Alignment.Right, font: GUI.SmallFont) { TextColor = textBlock.TextColor * 0.8f, ToolTip = textBlock.ToolTip diff --git a/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs index 3d0b38907..09d48fdbc 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs @@ -15,7 +15,7 @@ namespace Barotrauma { class MainMenuScreen : Screen { - public enum Tab { NewGame = 1, LoadGame = 2, HostServer = 3, Settings = 4, Tutorials = 5, JoinServer = 6, CharacterEditor = 7, SubmarineEditor = 8, QuickStartDev = 9, SteamWorkshop = 10 } + public enum Tab { NewGame = 1, LoadGame = 2, HostServer = 3, Settings = 4, Tutorials = 5, JoinServer = 6, CharacterEditor = 7, SubmarineEditor = 8, QuickStartDev = 9, SteamWorkshop = 10, Credits = 11 } private GUIComponent buttonsParent; @@ -35,22 +35,27 @@ namespace Barotrauma private Sprite backgroundSprite; private Sprite backgroundVignette; + private GUIComponent titleText; + + private CreditsPlayer creditsPlayer; + #region Creation public MainMenuScreen(GameMain game) { backgroundVignette = new Sprite("Content/UI/MainMenuVignette.png", Vector2.Zero); new GUIImage(new RectTransform(new Vector2(0.35f, 0.2f), Frame.RectTransform, Anchor.BottomRight) - { RelativeOffset = new Vector2(0.05f, 0.05f), AbsoluteOffset = new Point(-5, -5) }, + { RelativeOffset = new Vector2(0.05f, 0.1f), AbsoluteOffset = new Point(-8, -8) }, style: "TitleText") { Color = Color.Black * 0.5f, CanBeFocused = false }; - new GUIImage(new RectTransform(new Vector2(0.35f, 0.2f), Frame.RectTransform, Anchor.BottomRight) { RelativeOffset = new Vector2(0.05f, 0.05f) }, + titleText = new GUIImage(new RectTransform(new Vector2(0.35f, 0.2f), Frame.RectTransform, Anchor.BottomRight) + { RelativeOffset = new Vector2(0.05f, 0.1f) }, style: "TitleText"); - buttonsParent = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 0.85f), parent: Frame.RectTransform, anchor: Anchor.BottomLeft, pivot: Pivot.BottomLeft) + buttonsParent = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 0.85f), parent: Frame.RectTransform, anchor: Anchor.CenterLeft) { AbsoluteOffset = new Point(50, 0) }) @@ -223,7 +228,7 @@ namespace Barotrauma }; // === OPTION - var optionHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.5f), parent: buttonsParent.RectTransform), isHorizontal: true); + var optionHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.8f), parent: buttonsParent.RectTransform), isHorizontal: true); new GUIImage(new RectTransform(new Vector2(0.15f, 0.6f), optionHolder.RectTransform), "MainMenuOptionIcon") { @@ -233,9 +238,9 @@ namespace Barotrauma //spacing new GUIFrame(new RectTransform(new Vector2(0.01f, 0.0f), optionHolder.RectTransform), style: null); - var optionButtons = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 1.0f), parent: optionHolder.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.05f) }); + var optionButtons = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 1.0f), parent: optionHolder.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.0f) }); - var optionList = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 0.3f), parent: optionButtons.RectTransform)) + var optionList = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 0.25f), parent: optionButtons.RectTransform)) { Stretch = false, RelativeSpacing = 0.035f @@ -247,6 +252,13 @@ namespace Barotrauma UserData = Tab.Settings, OnClicked = SelectTab }; + //TODO: translate + new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), optionList.RectTransform), TextManager.Get("CreditsButton"), textAlignment: Alignment.Left, style: "MainMenuGUIButton") + { + ForceUpperCase = true, + UserData = Tab.Credits, + OnClicked = SelectTab + }; new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), optionList.RectTransform), TextManager.Get("QuitButton"), textAlignment: Alignment.Left, style: "MainMenuGUIButton") { ForceUpperCase = true, @@ -255,9 +267,9 @@ namespace Barotrauma //debug button for quickly starting a new round #if DEBUG - new GUIButton(new RectTransform(new Vector2(0.8f, 0.1f), buttonsParent.RectTransform, Anchor.TopLeft, Pivot.BottomLeft) { AbsoluteOffset = new Point(0, -40) }, + new GUIButton(new RectTransform(new Point(300, 30), Frame.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point(40, 40) }, "Quickstart (dev)", style: "GUIButtonLarge", color: Color.Red) - { + { IgnoreLayoutGroups = true, UserData = Tab.QuickStartDev, OnClicked = (tb, userdata) => @@ -373,6 +385,8 @@ namespace Barotrauma { if (obj is Tab) { + titleText.Visible = true; + if (GameMain.Config.UnsavedSettings) { var applyBox = new GUIMessageBox( @@ -449,6 +463,9 @@ namespace Barotrauma if (!Steam.SteamManager.IsInitialized) return false; GameMain.SteamWorkshopScreen.Select(); break; + case Tab.Credits: + titleText.Visible = false; + break; } } else @@ -702,11 +719,6 @@ namespace Barotrauma public override void Update(double deltaTime) { - GameMain.TitleScreen.TitlePosition = - Vector2.Lerp(GameMain.TitleScreen.TitlePosition, new Vector2( - GameMain.TitleScreen.TitleSize.X / 2.0f * GameMain.TitleScreen.Scale + 30.0f, - GameMain.TitleScreen.TitleSize.Y / 2.0f * GameMain.TitleScreen.Scale + 30.0f), - 0.1f); #if !DEBUG #if !OSX if (Steam.SteamManager.USE_STEAM) @@ -780,27 +792,30 @@ namespace Barotrauma GUI.Font.DrawString(spriteBatch, "Barotrauma v" + GameMain.Version, new Vector2(10, GameMain.GraphicsHeight - 20), Color.White * 0.7f); #endif - Vector2 textPos = new Vector2(GameMain.GraphicsWidth - 10, GameMain.GraphicsHeight - 10); - for (int i = legalCrap.Length - 1; i >= 0; i--) + if (selectedTab != Tab.Credits) { - Vector2 textSize = GUI.SmallFont.MeasureString(legalCrap[i]); - bool mouseOn = i == 0 && - PlayerInput.MousePosition.X > textPos.X - textSize.X && PlayerInput.MousePosition.X < textPos.X && - PlayerInput.MousePosition.Y > textPos.Y - textSize.Y && PlayerInput.MousePosition.Y < textPos.Y; - - GUI.SmallFont.DrawString(spriteBatch, - legalCrap[i], textPos - textSize, - mouseOn ? Color.White : Color.White * 0.7f); - - if (i == 0) + Vector2 textPos = new Vector2(GameMain.GraphicsWidth - 10, GameMain.GraphicsHeight - 10); + for (int i = legalCrap.Length - 1; i >= 0; i--) { - GUI.DrawLine(spriteBatch, textPos, textPos - Vector2.UnitX * textSize.X, mouseOn ? Color.White : Color.White * 0.7f); - if (mouseOn && PlayerInput.LeftButtonClicked()) + Vector2 textSize = GUI.SmallFont.MeasureString(legalCrap[i]); + bool mouseOn = i == 0 && + PlayerInput.MousePosition.X > textPos.X - textSize.X && PlayerInput.MousePosition.X < textPos.X && + PlayerInput.MousePosition.Y > textPos.Y - textSize.Y && PlayerInput.MousePosition.Y < textPos.Y; + + GUI.SmallFont.DrawString(spriteBatch, + legalCrap[i], textPos - textSize, + mouseOn ? Color.White : Color.White * 0.7f); + + if (i == 0) { - Process.Start("http://privacypolicy.daedalic.com"); + GUI.DrawLine(spriteBatch, textPos, textPos - Vector2.UnitX * textSize.X, mouseOn ? Color.White : Color.White * 0.7f); + if (mouseOn && PlayerInput.LeftButtonClicked()) + { + Process.Start("http://privacypolicy.daedalic.com"); + } } + textPos.Y -= textSize.Y; } - textPos.Y -= textSize.Y; } spriteBatch.End(); diff --git a/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs index f136ff3a2..fd5dfbfd0 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs @@ -437,9 +437,13 @@ namespace Barotrauma GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), modeList.Content.RectTransform), mode.Name, style: "ListBoxElement", textAlignment: Alignment.CenterLeft) { - ToolTip = mode.Description, UserData = mode }; + //TODO: translate mission descriptions + if (TextManager.Language == "English") + { + textBlock.ToolTip = mode.Description; + } } //mission type ------------------------------------------------------------------ @@ -1216,7 +1220,7 @@ namespace Barotrauma if (sub.HasTag(SubmarineTag.Shuttle)) { new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), frame.RectTransform, Anchor.CenterRight) { RelativeOffset = new Vector2(0.1f, 0.0f) }, - TextManager.Get("Shuttle"), textAlignment: Alignment.CenterRight, font: GUI.SmallFont) + TextManager.Get("Shuttle", fallBackTag: "RespawnShuttle"), textAlignment: Alignment.CenterRight, font: GUI.SmallFont) { TextColor = subTextBlock.TextColor * 0.8f, ToolTip = subTextBlock.ToolTip, diff --git a/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs index 97d2e92a6..f0ae24fe4 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs @@ -1184,7 +1184,6 @@ namespace Barotrauma { OnClicked = SaveSub }; -#endif } @@ -1357,7 +1356,7 @@ namespace Barotrauma if (sub.HasTag(SubmarineTag.Shuttle)) { var shuttleText = new GUITextBlock(new RectTransform(new Vector2(0.2f, 1.0f), textBlock.RectTransform, Anchor.CenterRight), - TextManager.Get("Shuttle"), font: GUI.SmallFont) + TextManager.Get("Shuttle", fallBackTag: "RespawnShuttle"), font: GUI.SmallFont) { TextColor = textBlock.TextColor * 0.8f, ToolTip = textBlock.ToolTip diff --git a/Barotrauma/BarotraumaClient/Source/Serialization/SerializableEntityEditor.cs b/Barotrauma/BarotraumaClient/Source/Serialization/SerializableEntityEditor.cs index 6d244e815..fb6a86f1e 100644 --- a/Barotrauma/BarotraumaClient/Source/Serialization/SerializableEntityEditor.cs +++ b/Barotrauma/BarotraumaClient/Source/Serialization/SerializableEntityEditor.cs @@ -927,6 +927,7 @@ namespace Barotrauma textTag = textTag.ToLowerInvariant(); var tagTextPairs = TextManager.GetAllTagTextPairs(); + tagTextPairs.Sort((t1, t2) => { return t1.Value.CompareTo(t2.Value); }); foreach (KeyValuePair tagTextPair in tagTextPairs) { if (!tagTextPair.Key.StartsWith(textTag)) { continue; } diff --git a/Barotrauma/BarotraumaClient/Source/Utils/LocalizationCSVtoXML.cs b/Barotrauma/BarotraumaClient/Source/Utils/LocalizationCSVtoXML.cs index a9ad8e446..7e76d6ad2 100644 --- a/Barotrauma/BarotraumaClient/Source/Utils/LocalizationCSVtoXML.cs +++ b/Barotrauma/BarotraumaClient/Source/Utils/LocalizationCSVtoXML.cs @@ -11,7 +11,7 @@ namespace Barotrauma { private static Regex csvSplit = new Regex("(?:^|,)(\"(?:[^\"])*\"|[^,]*)", RegexOptions.Compiled); // Handling commas inside data fields surrounded by "" private static List conversationClosingIndent = new List(); - private static char[] separator = new char[1] { ',' }; + private static char[] separator = new char[1] { '|' }; private const string conversationsPath = "Content/NPCConversations"; private const string infoTextPath = "Content/Texts"; @@ -48,7 +48,7 @@ namespace Barotrauma DebugConsole.ThrowError("NPCConversation Localization .csv to .xml conversion failed for: " + conversationFiles[i]); continue; } - string xmlFileFullPath = $"{conversationsPath}/NPCConversations_{language}_NEW.xml"; + string xmlFileFullPath = $"{conversationsPath}/NpcConversations_{language}_NEW.xml"; File.WriteAllLines(xmlFileFullPath, xmlContent); DebugConsole.NewMessage("Conversation localization .xml file successfully created at: " + xmlFileFullPath); } @@ -141,7 +141,8 @@ namespace Barotrauma for (int i = 0; i < NPCPersonalityTrait.List.Count; i++) // Traits { - string[] split = SplitCSV(csvContent[traitStart + i].Trim(separator)); + //string[] split = SplitCSV(csvContent[traitStart + i].Trim(separator)); + string[] split = csvContent[traitStart + i].Split(separator); xmlContent.Add( $" words = new List(); + string currWord = ""; + for (int i = 0; i < text.Length; i++) { - words = new string[text.Length]; - for (int i = 0; i < text.Length; i++) + if (isCJK.IsMatch(text[i].ToString())) { - words[i] = text[i].ToString(); + if (currWord.Length > 0) + { + words.Add(currWord); + currWord = ""; + } + words.Add(text[i].ToString()); + } + else if (text[i] == ' ') + { + if (currWord.Length > 0) + { + words.Add(currWord); + currWord = ""; + } + } + else + { + currWord += text[i]; } } - else + if (currWord.Length > 0) { - words = text.Split(' '); + words.Add(currWord); + currWord = ""; } StringBuilder wrappedText = new StringBuilder(); float linePos = 0f; Vector2 spaceSize = font.MeasureString(" ") * textScale; - for (int i = 0; i < words.Length; ++i) + for (int i = 0; i < words.Count; ++i) { if (words[i].Length == 0) { diff --git a/Barotrauma/BarotraumaShared/Data/ContentPackages/Vanilla 0.9.xml b/Barotrauma/BarotraumaShared/Data/ContentPackages/Vanilla 0.9.xml index b7b5d6657..3bd2357dd 100644 --- a/Barotrauma/BarotraumaShared/Data/ContentPackages/Vanilla 0.9.xml +++ b/Barotrauma/BarotraumaShared/Data/ContentPackages/Vanilla 0.9.xml @@ -73,6 +73,7 @@ + @@ -83,8 +84,12 @@ - - + + + + + + @@ -98,7 +103,13 @@ - + + + + + + + diff --git a/Barotrauma/BarotraumaShared/SharedContent.projitems b/Barotrauma/BarotraumaShared/SharedContent.projitems index 8ac5b0f8f..f9667893d 100644 --- a/Barotrauma/BarotraumaShared/SharedContent.projitems +++ b/Barotrauma/BarotraumaShared/SharedContent.projitems @@ -361,6 +361,12 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -499,10 +505,47 @@ PreserveNewest - + PreserveNewest - + + PreserveNewest + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + PreserveNewest @@ -556,6 +599,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -1306,11 +1352,6 @@ PreserveNewest - - - - PreserveNewest - PreserveNewest @@ -2070,6 +2111,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFixLeak.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFixLeak.cs index 081c446d7..9652b612f 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFixLeak.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFixLeak.cs @@ -150,6 +150,31 @@ namespace Barotrauma { #if DEBUG DebugConsole.ThrowError("AIObjectiveFixLeak failed - the item \"" + weldingTool + "\" has no RepairTool component but is tagged as a welding tool"); +#endif + abandon = true; + return; + } + Vector2 gapDiff = Leak.WorldPosition - character.WorldPosition; + // TODO: use the collider size/reach? + if (!character.AnimController.InWater && Math.Abs(gapDiff.X) < 100 && gapDiff.Y < 0.0f && gapDiff.Y > -150) + { + HumanAIController.AnimController.Crouching = true; + } + float reach = ConvertUnits.ToSimUnits(repairTool.Range); + bool canOperate = ConvertUnits.ToSimUnits(gapDiff.Length()) < reach; + if (canOperate) + { + TryAddSubObjective(ref operateObjective, () => new AIObjectiveOperateItem(repairTool, character, objectiveManager, option: "", requireEquip: true, operateTarget: Leak)); + } + else + { + TryAddSubObjective(ref gotoObjective, () => new AIObjectiveGoTo(ConvertUnits.ToSimUnits(GetStandPosition()), character, objectiveManager) { CloseEnough = reach * 0.75f }); + } + var repairTool = weldingTool.GetComponent(); + if (repairTool == null) + { +#if DEBUG + DebugConsole.ThrowError("AIObjectiveFixLeak failed - the item \"" + weldingTool + "\" has no RepairTool component but is tagged as a welding tool"); #endif abandon = true; return; diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveIdle.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveIdle.cs index 34e4fad8c..cf391c49b 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveIdle.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveIdle.cs @@ -74,6 +74,21 @@ namespace Barotrauma } } + public override void Update(float deltaTime) + { + if (objectiveManager.CurrentObjective == this) + { + if (randomTimer > 0) + { + randomTimer -= deltaTime; + } + else + { + SetRandom(); + } + } + } + public override bool IsCompleted() => false; public override bool CanBeCompleted => true; diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs index ae25abb64..599226af7 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs @@ -94,6 +94,10 @@ namespace Barotrauma { isCompleted = true; } + if (component.AIOperate(deltaTime, character, this)) + { + isCompleted = true; + } } else { diff --git a/Barotrauma/BarotraumaShared/Source/GameSettings.cs b/Barotrauma/BarotraumaShared/Source/GameSettings.cs index 87d52b889..469a636b6 100644 --- a/Barotrauma/BarotraumaShared/Source/GameSettings.cs +++ b/Barotrauma/BarotraumaShared/Source/GameSettings.cs @@ -279,6 +279,8 @@ namespace Barotrauma } public static bool ShowUserStatisticsPrompt { get; set; } + public bool ShowLanguageSelectionPrompt { get; set; } + public GameSettings() { SelectedContentPackages = new HashSet(); @@ -764,6 +766,7 @@ namespace Barotrauma CheckBindings(!fileFound); if (!fileFound) { + ShowLanguageSelectionPrompt = true; SaveNewPlayerConfig(); } } @@ -916,6 +919,71 @@ namespace Barotrauma selectedContentPackagePaths = new HashSet(); + foreach (XElement subElement in doc.Root.Elements()) + { + switch (subElement.Name.ToString().ToLowerInvariant()) + { + case "keymapping": + foreach (XAttribute attribute in subElement.Attributes()) + { + if (Enum.TryParse(attribute.Name.ToString(), true, out InputType inputType)) + { + if (int.TryParse(attribute.Value.ToString(), out int mouseButton)) + { + keyMapping[(int)inputType] = new KeyOrMouse(mouseButton); + } + else + { + if (Enum.TryParse(attribute.Value.ToString(), true, out Keys key)) + { + keyMapping[(int)inputType] = new KeyOrMouse(key); + } + } + } + } + break; + case "gameplay": + jobPreferences = new List(); + foreach (XElement ele in subElement.Element("jobpreferences").Elements("job")) + { + string jobIdentifier = ele.GetAttributeString("identifier", ""); + if (string.IsNullOrEmpty(jobIdentifier)) continue; + jobPreferences.Add(jobIdentifier); + } + break; + case "player": + defaultPlayerName = subElement.GetAttributeString("name", defaultPlayerName); + CharacterHeadIndex = subElement.GetAttributeInt("headindex", CharacterHeadIndex); + if (Enum.TryParse(subElement.GetAttributeString("gender", "none"), true, out Gender g)) + { + CharacterGender = g; + } + if (Enum.TryParse(subElement.GetAttributeString("race", "white"), true, out Race r)) + { + CharacterRace = r; + } + else + { + CharacterRace = Race.White; + } + CharacterHairIndex = subElement.GetAttributeInt("hairindex", CharacterHairIndex); + CharacterBeardIndex = subElement.GetAttributeInt("beardindex", CharacterBeardIndex); + CharacterMoustacheIndex = subElement.GetAttributeInt("moustacheindex", CharacterMoustacheIndex); + CharacterFaceAttachmentIndex = subElement.GetAttributeInt("faceattachmentindex", CharacterFaceAttachmentIndex); + break; + case "tutorials": + foreach (XElement tutorialElement in subElement.Elements()) + { + CompletedTutorialNames.Add(tutorialElement.GetAttributeString("name", "")); + } + break; + } + } + + UnsavedSettings = false; + + selectedContentPackagePaths = new HashSet(); + foreach (XElement subElement in doc.Root.Elements()) { DebugConsole.ThrowError(TextManager.Get("ContentPackageNotFound").Replace("[packagepath]", missingPackagePath)); diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Controller.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Controller.cs index 2509f5d2f..ba73f2cf5 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Controller.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Controller.cs @@ -43,6 +43,11 @@ namespace Barotrauma.Items.Components set { userPos = value; } } + public Character User + { + get { return user; } + } + public Controller(Item item, XElement element) : base(item, element) { @@ -163,7 +168,7 @@ namespace Barotrauma.Items.Components return false; } - item.SendSignal(0, "1", "trigger_out", character); + item.SendSignal(0, "1", "trigger_out", user); ApplyStatusEffects(ActionType.OnUse, 1.0f, activator); @@ -233,7 +238,7 @@ namespace Barotrauma.Items.Components private Item GetFocusTarget() { - item.SendSignal(0, MathHelper.ToDegrees(targetRotation).ToString("G", CultureInfo.InvariantCulture), "position_out", character); + item.SendSignal(0, MathHelper.ToDegrees(targetRotation).ToString("G", CultureInfo.InvariantCulture), "position_out", user); for (int i = item.LastSentSignalRecipients.Count - 1; i >= 0; i--) { diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Deconstructor.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Deconstructor.cs index bf78419aa..2b2d6255a 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Deconstructor.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Deconstructor.cs @@ -601,6 +601,25 @@ namespace Barotrauma.Items.Components } } + if (targetItem.Prefab.DeconstructItems.Any()) + { + inputContainer.Inventory.RemoveItem(targetItem); + Entity.Spawner.AddToRemoveQueue(targetItem); + MoveInputQueue(); + PutItemsToLinkedContainer(); + } + else + { + if (outputContainer.Inventory.Items.All(i => i != null)) + { + targetItem.Drop(dropper: null); + } + else + { + outputContainer.Inventory.TryPutItem(targetItem, user: null, createNetworkEvent: true); + } + } + if (targetItem.Prefab.DeconstructItems.Any()) { inputContainer.Inventory.RemoveItem(targetItem); diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs index a251165ce..2aafee648 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs @@ -212,33 +212,6 @@ namespace Barotrauma.Items.Components } } - public Vector2? PosToMaintain - { - get { return posToMaintain; } - set { posToMaintain = value; } - } - - struct ObstacleDebugInfo - { - public Vector2 Point1; - public Vector2 Point2; - - public Vector2? Intersection; - - public float Dot; - - public Vector2 AvoidStrength; - - public ObstacleDebugInfo(GraphEdge edge, Vector2? intersection, float dot, Vector2 avoidStrength) - { - Point1 = edge.Point1; - Point2 = edge.Point2; - Intersection = intersection; - Dot = dot; - AvoidStrength = avoidStrength; - } - } - //edge point 1, edge point 2, avoid strength private List debugDrawObstacles = new List(); diff --git a/Barotrauma/BarotraumaShared/Source/Items/Item.cs b/Barotrauma/BarotraumaShared/Source/Items/Item.cs index 858ab32dc..3cbfb6b1b 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Item.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Item.cs @@ -1640,6 +1640,10 @@ namespace Barotrauma { ApplyStatusEffects(!waterProof && inWater ? ActionType.InWater : ActionType.NotInWater, deltaTime); } + if (!broken) + { + ApplyStatusEffects(!waterProof && inWater ? ActionType.InWater : ActionType.NotInWater, deltaTime); + } ApplyStatusEffects(!waterProof && inWater ? ActionType.InWater : ActionType.NotInWater, deltaTime); if (body == null || !body.Enabled || !inWater || ParentInventory != null || Removed) { return; } diff --git a/Barotrauma/BarotraumaShared/Source/Map/Hull.cs b/Barotrauma/BarotraumaShared/Source/Map/Hull.cs index 3e934a177..a4d39eb42 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Hull.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Hull.cs @@ -227,6 +227,25 @@ namespace Barotrauma } } + public string DisplayName + { + get; + private set; + } + + private string roomName; + [Editable, Serialize("", true, translationTextTag: "RoomName.")] + public string RoomName + { + get { return roomName; } + set + { + if (roomName == value) { return; } + roomName = value; + DisplayName = TextManager.Get(roomName, returnNull: true) ?? roomName; + } + } + public override Rectangle Rect { get diff --git a/Barotrauma/BarotraumaShared/Source/Sprite/Sprite.cs b/Barotrauma/BarotraumaShared/Source/Sprite/Sprite.cs index 064b5d1e2..26059513f 100644 --- a/Barotrauma/BarotraumaShared/Source/Sprite/Sprite.cs +++ b/Barotrauma/BarotraumaShared/Source/Sprite/Sprite.cs @@ -109,6 +109,11 @@ namespace Barotrauma if (!ParseTexturePath(path, file)) { return; } Name = SourceElement.GetAttributeString("name", null); Vector4 sourceVector = SourceElement.GetAttributeVector4("sourcerect", Vector4.Zero); + var overrideElement = GetLocalizationOverrideElement(); + if (overrideElement != null && overrideElement.Attribute("sourcerect") != null) + { + sourceVector = overrideElement.GetAttributeVector4("sourcerect", Vector4.Zero); + } preMultipliedAlpha = preMultiplyAlpha ?? SourceElement.GetAttributeBool("premultiplyalpha", true); bool shouldReturn = false; if (!lazyLoad) @@ -240,8 +245,12 @@ namespace Barotrauma } if (SourceElement != null) { - Vector4 sourceVector = SourceElement.GetAttributeVector4("sourcerect", Vector4.Zero); - sourceRect = new Rectangle((int)sourceVector.X, (int)sourceVector.Y, (int)sourceVector.Z, (int)sourceVector.W); + sourceRect = SourceElement.GetAttributeRect("sourcerect", Rectangle.Empty); + var overrideElement = GetLocalizationOverrideElement(); + if (overrideElement != null && overrideElement.Attribute("sourcerect") != null) + { + sourceRect = overrideElement.GetAttributeRect("sourcerect", Rectangle.Empty); + } size = SourceElement.GetAttributeVector2("size", Vector2.One); size.X *= sourceRect.Width; size.Y *= sourceRect.Height; @@ -256,6 +265,12 @@ namespace Barotrauma if (file == "") { file = SourceElement.GetAttributeString("texture", ""); + var overrideElement = GetLocalizationOverrideElement(); + if (overrideElement != null) + { + string overrideFile = overrideElement.GetAttributeString("texture", ""); + if (!string.IsNullOrEmpty(overrideFile)) { file = overrideFile; } + } } if (file == "") { @@ -273,6 +288,22 @@ namespace Barotrauma } return true; } + + private XElement GetLocalizationOverrideElement() + { + foreach (XElement subElement in SourceElement.Elements()) + { + if (subElement.Name.ToString().ToLowerInvariant() == "override") + { + string language = subElement.GetAttributeString("language", ""); + if (TextManager.Language.ToLower() == language.ToLower()) + { + return subElement; + } + } + } + return null; + } } } diff --git a/Barotrauma/BarotraumaShared/Source/TextManager.cs b/Barotrauma/BarotraumaShared/Source/TextManager.cs index 466c12c65..27d1966d0 100644 --- a/Barotrauma/BarotraumaShared/Source/TextManager.cs +++ b/Barotrauma/BarotraumaShared/Source/TextManager.cs @@ -16,14 +16,6 @@ namespace Barotrauma private static string[] serverMessageCharacters = new string[] { "~", "[", "]", "=" }; public static string Language; - public static bool NoWhiteSpace - { - get - { - if (!textPacks.ContainsKey(Language)) { return false; } - return textPacks[Language].Any(t => t.NoWhiteSpace); - } - } private static HashSet availableLanguages = new HashSet(); public static IEnumerable AvailableLanguages @@ -87,7 +79,7 @@ namespace Barotrauma } } - public static string Get(string textTag, bool returnNull = false) + public static string Get(string textTag, bool returnNull = false, string fallBackTag = null) { if (!textPacks.ContainsKey(Language)) { @@ -102,7 +94,16 @@ namespace Barotrauma foreach (TextPack textPack in textPacks[Language]) { string text = textPack.Get(textTag); - if (text != null) return text; + if (text != null) { return text; } + } + + if (!string.IsNullOrEmpty(fallBackTag)) + { + foreach (TextPack textPack in textPacks[Language]) + { + string text = textPack.Get(fallBackTag); + if (text != null) { return text; } + } } //if text was not found and we're using a language other than English, see if we can find an English version diff --git a/Barotrauma/BarotraumaShared/Source/TextPack.cs b/Barotrauma/BarotraumaShared/Source/TextPack.cs index a4105c57b..18b0170d8 100644 --- a/Barotrauma/BarotraumaShared/Source/TextPack.cs +++ b/Barotrauma/BarotraumaShared/Source/TextPack.cs @@ -11,9 +11,7 @@ namespace Barotrauma public readonly string Language; private Dictionary> texts; - - public readonly bool NoWhiteSpace; - + private readonly string filePath; public TextPack(string filePath) @@ -25,7 +23,6 @@ namespace Barotrauma if (doc == null || doc.Root == null) return; Language = doc.Root.GetAttributeString("language", "Unknown"); - NoWhiteSpace = doc.Root.GetAttributeBool("nowhitespace", false); foreach (XElement subElement in doc.Root.Elements()) { diff --git a/Barotrauma/BarotraumaShared/Source/Utils/SaveUtil.cs b/Barotrauma/BarotraumaShared/Source/Utils/SaveUtil.cs index 25400d5f1..f27815971 100644 --- a/Barotrauma/BarotraumaShared/Source/Utils/SaveUtil.cs +++ b/Barotrauma/BarotraumaShared/Source/Utils/SaveUtil.cs @@ -393,7 +393,9 @@ namespace Barotrauma { using (FileStream inFile = new FileStream(sCompressedFile, FileMode.Open, FileAccess.Read, FileShare.None)) using (GZipStream zipStream = new GZipStream(inFile, CompressionMode.Decompress, true)) - while (DecompressFile(sDir, zipStream, progress)) ; + while (DecompressFile(sDir, zipStream, progress)) { }; + + break; } catch (IOException e) { diff --git a/Barotrauma/BarotraumaShared/Submarines/Bunyip.sub b/Barotrauma/BarotraumaShared/Submarines/Bunyip.sub index 8451d5027..0963b9725 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Bunyip.sub and b/Barotrauma/BarotraumaShared/Submarines/Bunyip.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub index 63845bb03..1faf47a55 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub and b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Humpback.sub b/Barotrauma/BarotraumaShared/Submarines/Humpback.sub index 51d51cc70..751bb85a9 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Humpback.sub and b/Barotrauma/BarotraumaShared/Submarines/Humpback.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Orca.sub b/Barotrauma/BarotraumaShared/Submarines/Orca.sub index b89be561c..45b257e88 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Orca.sub and b/Barotrauma/BarotraumaShared/Submarines/Orca.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Remora.sub b/Barotrauma/BarotraumaShared/Submarines/Remora.sub index c874b9710..b11988da2 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Remora.sub and b/Barotrauma/BarotraumaShared/Submarines/Remora.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/RemoraDrone.sub b/Barotrauma/BarotraumaShared/Submarines/RemoraDrone.sub index db200977b..2f11785db 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/RemoraDrone.sub and b/Barotrauma/BarotraumaShared/Submarines/RemoraDrone.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Selkie.sub b/Barotrauma/BarotraumaShared/Submarines/Selkie.sub index 59dc7cc11..2c29b9f4a 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Selkie.sub and b/Barotrauma/BarotraumaShared/Submarines/Selkie.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Typhon.sub b/Barotrauma/BarotraumaShared/Submarines/Typhon.sub index 0a18b4090..1123d84b8 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Typhon.sub and b/Barotrauma/BarotraumaShared/Submarines/Typhon.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Venture.sub b/Barotrauma/BarotraumaShared/Submarines/Venture.sub index f06df8916..7fe946301 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Venture.sub and b/Barotrauma/BarotraumaShared/Submarines/Venture.sub differ