Merge branch 'master' of https://github.com/Regalis11/Barotrauma.git
This commit is contained in:
@@ -116,7 +116,7 @@ namespace Barotrauma
|
|||||||
Stretch = true
|
Stretch = true
|
||||||
};
|
};
|
||||||
|
|
||||||
var skills = Job.Skills;
|
var skills = Job.GetSkills().ToList();
|
||||||
skills.Sort((s1, s2) => -s1.Level.CompareTo(s2.Level));
|
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 };
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), skillsArea.RectTransform), TextManager.AddPunctuation(':', TextManager.Get("skills"), string.Empty), font: font) { Padding = Vector4.Zero };
|
||||||
@@ -560,17 +560,7 @@ namespace Barotrauma
|
|||||||
ch.SetPersonalityTrait();
|
ch.SetPersonalityTrait();
|
||||||
if (ch.Job != null)
|
if (ch.Job != null)
|
||||||
{
|
{
|
||||||
foreach (KeyValuePair<Identifier, float> skill in skillLevels)
|
ch.Job.OverrideSkills(skillLevels);
|
||||||
{
|
|
||||||
Skill matchingSkill = ch.Job.Skills.Find(s => s.Identifier == skill.Key);
|
|
||||||
if (matchingSkill == null)
|
|
||||||
{
|
|
||||||
ch.Job.Skills.Add(new Skill(skill.Key, skill.Value));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
matchingSkill.Level = skill.Value;
|
|
||||||
}
|
|
||||||
ch.Job.Skills.RemoveAll(s => !skillLevels.ContainsKey(s.Identifier));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ch.ExperiencePoints = inc.ReadUInt16();
|
ch.ExperiencePoints = inc.ReadUInt16();
|
||||||
|
|||||||
@@ -694,6 +694,7 @@ namespace Barotrauma
|
|||||||
AssignRelayToServer("simulatedlatency", false);
|
AssignRelayToServer("simulatedlatency", false);
|
||||||
AssignRelayToServer("simulatedloss", false);
|
AssignRelayToServer("simulatedloss", false);
|
||||||
AssignRelayToServer("simulatedduplicateschance", false);
|
AssignRelayToServer("simulatedduplicateschance", false);
|
||||||
|
AssignRelayToServer("simulatedlongloadingtime", false);
|
||||||
AssignRelayToServer("storeinfo", false);
|
AssignRelayToServer("storeinfo", false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using PlayerBalanceElement = Barotrauma.CampaignUI.PlayerBalanceElement;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -21,6 +22,8 @@ namespace Barotrauma
|
|||||||
private GUIButton validateHiresButton;
|
private GUIButton validateHiresButton;
|
||||||
private GUIButton clearAllButton;
|
private GUIButton clearAllButton;
|
||||||
|
|
||||||
|
private PlayerBalanceElement? playerBalanceElement;
|
||||||
|
|
||||||
private List<CharacterInfo> PendingHires => campaign.Map?.CurrentLocation?.HireManager?.PendingHires;
|
private List<CharacterInfo> PendingHires => campaign.Map?.CurrentLocation?.HireManager?.PendingHires;
|
||||||
private bool HasPermission => campaignUI.Campaign.AllowedToManageCampaign(ClientPermissions.ManageHires);
|
private bool HasPermission => campaignUI.Campaign.AllowedToManageCampaign(ClientPermissions.ManageHires);
|
||||||
|
|
||||||
@@ -157,23 +160,7 @@ namespace Barotrauma
|
|||||||
RelativeSpacing = 0.02f
|
RelativeSpacing = 0.02f
|
||||||
};
|
};
|
||||||
|
|
||||||
var playerBalanceContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.75f / 14.0f), pendingAndCrewMainGroup.RectTransform), childAnchor: Anchor.TopRight)
|
playerBalanceElement = CampaignUI.AddBalanceElement(pendingAndCrewMainGroup, new Vector2(1.0f, 0.75f / 14.0f));
|
||||||
{
|
|
||||||
RelativeSpacing = 0.005f
|
|
||||||
};
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), playerBalanceContainer.RectTransform),
|
|
||||||
TextManager.Get("campaignstore.balance"), font: GUIStyle.Font, textAlignment: Alignment.BottomRight)
|
|
||||||
{
|
|
||||||
AutoScaleVertical = true,
|
|
||||||
ForceUpperCase = ForceUpperCase.Yes
|
|
||||||
};
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), playerBalanceContainer.RectTransform),
|
|
||||||
"", font: GUIStyle.SubHeadingFont, textAlignment: Alignment.TopRight)
|
|
||||||
{
|
|
||||||
AutoScaleVertical = true,
|
|
||||||
TextScale = 1.1f,
|
|
||||||
TextGetter = () => TextManager.FormatCurrency(campaign.Wallet.Balance)
|
|
||||||
};
|
|
||||||
|
|
||||||
var pendingAndCrewGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), anchor: Anchor.Center,
|
var pendingAndCrewGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), anchor: Anchor.Center,
|
||||||
parent: new GUIFrame(new RectTransform(new Vector2(1.0f, 13.25f / 14.0f), pendingAndCrewMainGroup.RectTransform)
|
parent: new GUIFrame(new RectTransform(new Vector2(1.0f, 13.25f / 14.0f), pendingAndCrewMainGroup.RectTransform)
|
||||||
@@ -344,7 +331,7 @@ namespace Barotrauma
|
|||||||
Color? jobColor = null;
|
Color? jobColor = null;
|
||||||
if (characterInfo.Job != null)
|
if (characterInfo.Job != null)
|
||||||
{
|
{
|
||||||
skill = characterInfo.Job?.PrimarySkill ?? characterInfo.Job.Skills.OrderByDescending(s => s.Level).FirstOrDefault();
|
skill = characterInfo.Job?.PrimarySkill ?? characterInfo.Job.GetSkills().OrderByDescending(s => s.Level).FirstOrDefault();
|
||||||
jobColor = characterInfo.Job.Prefab.UIColor;
|
jobColor = characterInfo.Job.Prefab.UIColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -547,8 +534,8 @@ namespace Barotrauma
|
|||||||
GUILayoutGroup skillGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.475f), mainGroup.RectTransform), isHorizontal: true);
|
GUILayoutGroup skillGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.475f), mainGroup.RectTransform), isHorizontal: true);
|
||||||
GUILayoutGroup skillNameGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 1.0f), skillGroup.RectTransform));
|
GUILayoutGroup skillNameGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 1.0f), skillGroup.RectTransform));
|
||||||
GUILayoutGroup skillLevelGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.2f, 1.0f), skillGroup.RectTransform));
|
GUILayoutGroup skillLevelGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.2f, 1.0f), skillGroup.RectTransform));
|
||||||
List<Skill> characterSkills = characterInfo.Job.Skills;
|
var characterSkills = characterInfo.Job.GetSkills();
|
||||||
blockHeight = 1.0f / characterSkills.Count;
|
blockHeight = 1.0f / characterSkills.Count();
|
||||||
foreach (Skill skill in characterSkills)
|
foreach (Skill skill in characterSkills)
|
||||||
{
|
{
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), skillNameGroup.RectTransform), TextManager.Get("SkillName." + skill.Identifier));
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), skillNameGroup.RectTransform), TextManager.Get("SkillName." + skill.Identifier));
|
||||||
@@ -630,7 +617,7 @@ namespace Barotrauma
|
|||||||
total += ((InfoSkill)c.UserData).CharacterInfo.Salary;
|
total += ((InfoSkill)c.UserData).CharacterInfo.Salary;
|
||||||
});
|
});
|
||||||
totalBlock.Text = TextManager.FormatCurrency(total);
|
totalBlock.Text = TextManager.FormatCurrency(total);
|
||||||
bool enoughMoney = campaign == null || campaign.Wallet.CanAfford(total);
|
bool enoughMoney = campaign == null || campaign.CanAfford(total);
|
||||||
totalBlock.TextColor = enoughMoney ? Color.White : Color.Red;
|
totalBlock.TextColor = enoughMoney ? Color.White : Color.Red;
|
||||||
validateHiresButton.Enabled = enoughMoney && HasPermission && pendingList.Content.RectTransform.Children.Any();
|
validateHiresButton.Enabled = enoughMoney && HasPermission && pendingList.Content.RectTransform.Children.Any();
|
||||||
}
|
}
|
||||||
@@ -652,7 +639,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
int total = nonDuplicateHires.Aggregate(0, (total, info) => total + info.Salary);
|
int total = nonDuplicateHires.Aggregate(0, (total, info) => total + info.Salary);
|
||||||
|
|
||||||
if (!campaign.Wallet.CanAfford(total)) { return false; }
|
if (!campaign.CanAfford(total)) { return false; }
|
||||||
|
|
||||||
bool atLeastOneHired = false;
|
bool atLeastOneHired = false;
|
||||||
foreach (CharacterInfo ci in nonDuplicateHires)
|
foreach (CharacterInfo ci in nonDuplicateHires)
|
||||||
@@ -792,6 +779,10 @@ namespace Barotrauma
|
|||||||
CreateUI();
|
CreateUI();
|
||||||
UpdateLocationView(campaign.Map.CurrentLocation, false);
|
UpdateLocationView(campaign.Map.CurrentLocation, false);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
playerBalanceElement = CampaignUI.UpdateBalanceElement(playerBalanceElement);
|
||||||
|
}
|
||||||
|
|
||||||
(GUIComponent highlightedFrame, CharacterInfo highlightedInfo) = FindHighlightedCharacter(GUI.MouseOn);
|
(GUIComponent highlightedFrame, CharacterInfo highlightedInfo) = FindHighlightedCharacter(GUI.MouseOn);
|
||||||
if (highlightedFrame != null && highlightedInfo != null)
|
if (highlightedFrame != null && highlightedInfo != null)
|
||||||
|
|||||||
@@ -567,9 +567,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
GameMain.GameSession?.EventManager?.DrawPinnedEvent(spriteBatch);
|
GameMain.GameSession?.EventManager?.DrawPinnedEvent(spriteBatch);
|
||||||
|
|
||||||
if (HUDLayoutSettings.DebugDraw) HUDLayoutSettings.Draw(spriteBatch);
|
if (HUDLayoutSettings.DebugDraw) { HUDLayoutSettings.Draw(spriteBatch); }
|
||||||
|
|
||||||
if (GameMain.Client != null) GameMain.Client.Draw(spriteBatch);
|
GameMain.Client?.Draw(spriteBatch);
|
||||||
|
|
||||||
if (Character.Controlled?.Inventory != null)
|
if (Character.Controlled?.Inventory != null)
|
||||||
{
|
{
|
||||||
@@ -616,28 +616,46 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
DrawSavingIndicator(spriteBatch);
|
DrawSavingIndicator(spriteBatch);
|
||||||
|
DrawCursor(spriteBatch);
|
||||||
if (GameMain.WindowActive && !HideCursor)
|
|
||||||
{
|
|
||||||
spriteBatch.End();
|
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: SamplerStateClamp, rasterizerState: GameMain.ScissorTestEnable);
|
|
||||||
|
|
||||||
if (GameMain.GameSession?.CrewManager is { DraggedOrderPrefab: { SymbolSprite: { } orderSprite, Color: var color }, DragOrder: true })
|
|
||||||
{
|
|
||||||
float spriteSize = Math.Max(orderSprite.size.X, orderSprite.size.Y);
|
|
||||||
orderSprite.Draw(spriteBatch, PlayerInput.LatestMousePosition, color, orderSprite.size / 2f, scale: 32f / spriteSize * Scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
var sprite = MouseCursorSprites[MouseCursor] ?? MouseCursorSprites[CursorState.Default];
|
|
||||||
sprite.Draw(spriteBatch, PlayerInput.LatestMousePosition, Color.White, sprite.Origin, 0f, Scale / 1.5f);
|
|
||||||
|
|
||||||
spriteBatch.End();
|
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
|
||||||
}
|
|
||||||
HideCursor = false;
|
HideCursor = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void DrawMessageBoxesOnly(SpriteBatch spriteBatch)
|
||||||
|
{
|
||||||
|
bool anyDrawn = false;
|
||||||
|
foreach (var component in updateList)
|
||||||
|
{
|
||||||
|
component.DrawAuto(spriteBatch);
|
||||||
|
anyDrawn = true;
|
||||||
|
}
|
||||||
|
if (anyDrawn)
|
||||||
|
{
|
||||||
|
DrawCursor(spriteBatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawCursor(SpriteBatch spriteBatch)
|
||||||
|
{
|
||||||
|
if (GameMain.WindowActive && !HideCursor && MouseCursorSprites.Prefabs.Any())
|
||||||
|
{
|
||||||
|
spriteBatch.End();
|
||||||
|
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: SamplerStateClamp, rasterizerState: GameMain.ScissorTestEnable);
|
||||||
|
|
||||||
|
if (GameMain.GameSession?.CrewManager is { DraggedOrderPrefab: { SymbolSprite: { } orderSprite, Color: var color }, DragOrder: true })
|
||||||
|
{
|
||||||
|
float spriteSize = Math.Max(orderSprite.size.X, orderSprite.size.Y);
|
||||||
|
orderSprite.Draw(spriteBatch, PlayerInput.LatestMousePosition, color, orderSprite.size / 2f, scale: 32f / spriteSize * Scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
var sprite = MouseCursorSprites[MouseCursor] ?? MouseCursorSprites[CursorState.Default];
|
||||||
|
sprite.Draw(spriteBatch, PlayerInput.LatestMousePosition, Color.White, sprite.Origin, 0f, Scale / 1.5f);
|
||||||
|
|
||||||
|
spriteBatch.End();
|
||||||
|
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void DrawBackgroundSprite(SpriteBatch spriteBatch, Sprite backgroundSprite, float aberrationStrength = 1.0f)
|
public static void DrawBackgroundSprite(SpriteBatch spriteBatch, Sprite backgroundSprite, float aberrationStrength = 1.0f)
|
||||||
{
|
{
|
||||||
double aberrationT = (Timing.TotalTime * 0.5f);
|
double aberrationT = (Timing.TotalTime * 0.5f);
|
||||||
@@ -1204,6 +1222,17 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void UpdateGUIMessageBoxesOnly(float deltaTime)
|
||||||
|
{
|
||||||
|
GUIMessageBox.AddActiveToGUIUpdateList();
|
||||||
|
RefreshUpdateList();
|
||||||
|
UpdateMouseOn();
|
||||||
|
foreach (var c in updateList)
|
||||||
|
{
|
||||||
|
c.UpdateAuto(deltaTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void UpdateMessages(float deltaTime)
|
private static void UpdateMessages(float deltaTime)
|
||||||
{
|
{
|
||||||
lock (mutex)
|
lock (mutex)
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ namespace Barotrauma
|
|||||||
public string Tag { get; private set; }
|
public string Tag { get; private set; }
|
||||||
public bool Closed { get; private set; }
|
public bool Closed { get; private set; }
|
||||||
|
|
||||||
|
public bool DisplayInLoadingScreens;
|
||||||
|
|
||||||
public GUIImage Icon
|
public GUIImage Icon
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
@@ -451,6 +453,10 @@ namespace Barotrauma
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (messageBox.type != type) { continue; }
|
if (messageBox.type != type) { continue; }
|
||||||
|
if (!messageBox.DisplayInLoadingScreens && GameMain.Instance.LoadingScreenOpen)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// These are handled separately in GUI.HandlePersistingElements()
|
// These are handled separately in GUI.HandlePersistingElements()
|
||||||
if (MessageBoxes[i].UserData as string == "verificationprompt") { continue; }
|
if (MessageBoxes[i].UserData as string == "verificationprompt") { continue; }
|
||||||
|
|||||||
@@ -395,14 +395,13 @@ namespace Barotrauma
|
|||||||
origin = TextSize * 0.5f;
|
origin = TextSize * 0.5f;
|
||||||
|
|
||||||
origin.X = 0;
|
origin.X = 0;
|
||||||
if (textAlignment.HasFlag(Alignment.Left) && !overflowClipActive)
|
if (textAlignment.HasFlag(Alignment.Left))
|
||||||
{
|
{
|
||||||
textPos.X = padding.X;
|
textPos.X = padding.X;
|
||||||
}
|
}
|
||||||
if (textAlignment.HasFlag(Alignment.Right) || overflowClipActive)
|
if (textAlignment.HasFlag(Alignment.Right))
|
||||||
{
|
{
|
||||||
textPos.X = rect.Width - padding.Z;
|
textPos.X = rect.Width - padding.Z;
|
||||||
//origin.X = TextSize.X;
|
|
||||||
}
|
}
|
||||||
if (textAlignment.HasFlag(Alignment.Top))
|
if (textAlignment.HasFlag(Alignment.Top))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -453,24 +453,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (CaretEnabled)
|
if (CaretEnabled)
|
||||||
{
|
{
|
||||||
if (textBlock.OverflowClipActive)
|
HandleCaretBoundsOverflow();
|
||||||
{
|
|
||||||
float left = textBlock.Rect.X + textBlock.Padding.X;
|
|
||||||
if (CaretScreenPos.X < left)
|
|
||||||
{
|
|
||||||
float diff = left - CaretScreenPos.X;
|
|
||||||
textBlock.TextPos = new Vector2(textBlock.TextPos.X + diff, textBlock.TextPos.Y);
|
|
||||||
CalculateCaretPos();
|
|
||||||
}
|
|
||||||
|
|
||||||
float right = textBlock.Rect.Right - textBlock.Padding.Z;
|
|
||||||
if (CaretScreenPos.X > right)
|
|
||||||
{
|
|
||||||
float diff = CaretScreenPos.X - right;
|
|
||||||
textBlock.TextPos = new Vector2(textBlock.TextPos.X - diff, textBlock.TextPos.Y);
|
|
||||||
CalculateCaretPos();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
caretTimer += deltaTime;
|
caretTimer += deltaTime;
|
||||||
caretVisible = ((caretTimer * 1000.0f) % 1000) < 500;
|
caretVisible = ((caretTimer * 1000.0f) % 1000) < 500;
|
||||||
if (caretVisible && caretPosDirty)
|
if (caretVisible && caretPosDirty)
|
||||||
@@ -496,6 +479,29 @@ namespace Barotrauma
|
|||||||
textBlock.State = State;
|
textBlock.State = State;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandleCaretBoundsOverflow()
|
||||||
|
{
|
||||||
|
if (textBlock.OverflowClipActive)
|
||||||
|
{
|
||||||
|
CalculateCaretPos();
|
||||||
|
float left = textBlock.Rect.X + textBlock.Padding.X;
|
||||||
|
if (CaretScreenPos.X < left)
|
||||||
|
{
|
||||||
|
float diff = left - CaretScreenPos.X;
|
||||||
|
textBlock.TextPos = new Vector2(textBlock.TextPos.X + diff, textBlock.TextPos.Y);
|
||||||
|
CalculateCaretPos();
|
||||||
|
}
|
||||||
|
|
||||||
|
float right = textBlock.Rect.Right - textBlock.Padding.Z;
|
||||||
|
if (CaretScreenPos.X > right)
|
||||||
|
{
|
||||||
|
float diff = CaretScreenPos.X - right;
|
||||||
|
textBlock.TextPos = new Vector2(textBlock.TextPos.X - diff, textBlock.TextPos.Y);
|
||||||
|
CalculateCaretPos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void DrawCaretAndSelection(SpriteBatch spriteBatch, GUICustomComponent customComponent)
|
private void DrawCaretAndSelection(SpriteBatch spriteBatch, GUICustomComponent customComponent)
|
||||||
{
|
{
|
||||||
if (!Visible) { return; }
|
if (!Visible) { return; }
|
||||||
@@ -564,15 +570,33 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
RemoveSelectedText();
|
RemoveSelectedText();
|
||||||
}
|
}
|
||||||
Vector2 textPos = textBlock.TextPos;
|
using var _ = new TextPosPreservation(this);
|
||||||
bool wasOverflowClipActive = textBlock.OverflowClipActive;
|
|
||||||
if (SetText(Text.Insert(CaretIndex, input)))
|
if (SetText(Text.Insert(CaretIndex, input)))
|
||||||
{
|
{
|
||||||
CaretIndex = Math.Min(Text.Length, CaretIndex + input.Length);
|
CaretIndex = Math.Min(Text.Length, CaretIndex + input.Length);
|
||||||
OnTextChanged?.Invoke(this, Text);
|
OnTextChanged?.Invoke(this, Text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly ref struct TextPosPreservation
|
||||||
|
{
|
||||||
|
private readonly GUITextBox textBox;
|
||||||
|
private GUITextBlock textBlock => textBox.TextBlock;
|
||||||
|
private readonly bool wasOverflowClipActive;
|
||||||
|
private readonly Vector2 textPos;
|
||||||
|
|
||||||
|
public TextPosPreservation(GUITextBox tb)
|
||||||
|
{
|
||||||
|
textBox = tb;
|
||||||
|
wasOverflowClipActive = tb.TextBlock.OverflowClipActive;
|
||||||
|
textPos = tb.TextBlock.TextPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
if (textBlock.OverflowClipActive && wasOverflowClipActive && !MathUtils.NearlyEqual(textBlock.TextPos, textPos))
|
if (textBlock.OverflowClipActive && wasOverflowClipActive && !MathUtils.NearlyEqual(textBlock.TextPos, textPos))
|
||||||
{
|
{
|
||||||
textBlock.TextPos = textPos + Vector2.UnitX * Font.MeasureString(input).X * TextBlock.TextScale;
|
textBlock.TextPos = textPos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -587,6 +611,8 @@ namespace Barotrauma
|
|||||||
switch (command)
|
switch (command)
|
||||||
{
|
{
|
||||||
case '\b' when !Readonly: //backspace
|
case '\b' when !Readonly: //backspace
|
||||||
|
{
|
||||||
|
using var _ = new TextPosPreservation(this);
|
||||||
if (PlayerInput.KeyDown(Keys.LeftControl) || PlayerInput.KeyDown(Keys.RightControl))
|
if (PlayerInput.KeyDown(Keys.LeftControl) || PlayerInput.KeyDown(Keys.RightControl))
|
||||||
{
|
{
|
||||||
SetText(string.Empty, false);
|
SetText(string.Empty, false);
|
||||||
@@ -605,6 +631,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
OnTextChanged?.Invoke(this, Text);
|
OnTextChanged?.Invoke(this, Text);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case (char)0x3: // ctrl-c
|
case (char)0x3: // ctrl-c
|
||||||
CopySelectedText();
|
CopySelectedText();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Barotrauma.Extensions;
|
||||||
|
using Barotrauma.Media;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using Microsoft.Xna.Framework.Input;
|
using Microsoft.Xna.Framework.Input;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Xml.Linq;
|
|
||||||
using Barotrauma.Media;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Barotrauma.Extensions;
|
|
||||||
using System.Collections.Immutable;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -16,7 +14,7 @@ namespace Barotrauma
|
|||||||
private readonly Texture2D defaultBackgroundTexture, overlay;
|
private readonly Texture2D defaultBackgroundTexture, overlay;
|
||||||
private readonly SpriteSheet decorativeGraph, decorativeMap;
|
private readonly SpriteSheet decorativeGraph, decorativeMap;
|
||||||
private Texture2D currentBackgroundTexture;
|
private Texture2D currentBackgroundTexture;
|
||||||
private Sprite noiseSprite;
|
private readonly Sprite noiseSprite;
|
||||||
|
|
||||||
private string randText = "";
|
private string randText = "";
|
||||||
|
|
||||||
@@ -250,8 +248,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
GUI.DrawMessageBoxesOnly(spriteBatch);
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
|
|
||||||
spriteBatch.Begin(blendState: BlendState.Additive);
|
spriteBatch.Begin(blendState: BlendState.Additive);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using System.Diagnostics.CodeAnalysis;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Barotrauma.Extensions;
|
using Barotrauma.Extensions;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
|
using PlayerBalanceElement = Barotrauma.CampaignUI.PlayerBalanceElement;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -180,6 +181,8 @@ namespace Barotrauma
|
|||||||
private const float refreshTimerMax = 3f;
|
private const float refreshTimerMax = 3f;
|
||||||
private float refreshTimer = 0;
|
private float refreshTimer = 0;
|
||||||
|
|
||||||
|
private PlayerBalanceElement? playerBalanceElement;
|
||||||
|
|
||||||
public MedicalClinicUI(MedicalClinic clinic, GUIComponent parent)
|
public MedicalClinicUI(MedicalClinic clinic, GUIComponent parent)
|
||||||
{
|
{
|
||||||
medicalClinic = clinic;
|
medicalClinic = clinic;
|
||||||
@@ -271,7 +274,7 @@ namespace Barotrauma
|
|||||||
healList.PriceBlock.Text = TextManager.FormatCurrency(totalCost);
|
healList.PriceBlock.Text = TextManager.FormatCurrency(totalCost);
|
||||||
healList.PriceBlock.TextColor = GUIStyle.Red;
|
healList.PriceBlock.TextColor = GUIStyle.Red;
|
||||||
healList.HealButton.Enabled = false;
|
healList.HealButton.Enabled = false;
|
||||||
if (medicalClinic.GetWallet().CanAfford(totalCost))
|
if (medicalClinic.GetBalance() >= totalCost)
|
||||||
{
|
{
|
||||||
healList.PriceBlock.TextColor = GUIStyle.TextColorNormal;
|
healList.PriceBlock.TextColor = GUIStyle.TextColorNormal;
|
||||||
if (medicalClinic.PendingHeals.Any())
|
if (medicalClinic.PendingHeals.Any())
|
||||||
@@ -428,6 +431,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
container.ClearChildren();
|
container.ClearChildren();
|
||||||
pendingHealList = null;
|
pendingHealList = null;
|
||||||
|
playerBalanceElement = null;
|
||||||
int panelMaxWidth = (int)(GUI.xScale * (GUI.HorizontalAspectRatio < 1.4f ? 650 : 560));
|
int panelMaxWidth = (int)(GUI.xScale * (GUI.HorizontalAspectRatio < 1.4f ? 650 : 560));
|
||||||
|
|
||||||
GUIFrame paddedParent = new GUIFrame(new RectTransform(new Vector2(0.95f), container.RectTransform, Anchor.Center), style: null);
|
GUIFrame paddedParent = new GUIFrame(new RectTransform(new Vector2(0.95f), container.RectTransform, Anchor.Center), style: null);
|
||||||
@@ -458,19 +462,7 @@ namespace Barotrauma
|
|||||||
RelativeSpacing = 0.01f
|
RelativeSpacing = 0.01f
|
||||||
};
|
};
|
||||||
|
|
||||||
GUILayoutGroup balanceLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.1f), crewContent.RectTransform));
|
playerBalanceElement = CampaignUI.AddBalanceElement(crewContent, new Vector2(1f, 0.1f));
|
||||||
GUITextBlock balanceLabel = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), balanceLayout.RectTransform), TextManager.Get("campaignstore.balance"), textAlignment: Alignment.BottomRight, font: GUIStyle.Font)
|
|
||||||
{
|
|
||||||
AutoScaleVertical = true,
|
|
||||||
ForceUpperCase = ForceUpperCase.Yes
|
|
||||||
};
|
|
||||||
|
|
||||||
GUITextBlock moneyLabel = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), balanceLayout.RectTransform), string.Empty, textAlignment: Alignment.TopRight, font: GUIStyle.SubHeadingFont)
|
|
||||||
{
|
|
||||||
TextGetter = () => TextManager.FormatCurrency(medicalClinic.GetWallet().Balance),
|
|
||||||
AutoScaleVertical = true,
|
|
||||||
TextScale = 1.1f
|
|
||||||
};
|
|
||||||
|
|
||||||
GUIFrame crewBackground = new GUIFrame(new RectTransform(Vector2.One, crewContent.RectTransform));
|
GUIFrame crewBackground = new GUIFrame(new RectTransform(Vector2.One, crewContent.RectTransform));
|
||||||
|
|
||||||
@@ -577,7 +569,7 @@ namespace Barotrauma
|
|||||||
GUILayoutGroup buttonLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), footerLayout.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterRight);
|
GUILayoutGroup buttonLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), footerLayout.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterRight);
|
||||||
GUIButton healButton = new GUIButton(new RectTransform(new Vector2(0.33f, 1f), buttonLayout.RectTransform), TextManager.Get("medicalclinic.heal"))
|
GUIButton healButton = new GUIButton(new RectTransform(new Vector2(0.33f, 1f), buttonLayout.RectTransform), TextManager.Get("medicalclinic.heal"))
|
||||||
{
|
{
|
||||||
Enabled = medicalClinic.PendingHeals.Any() && medicalClinic.GetWallet().CanAfford(medicalClinic.GetTotalCost()),
|
Enabled = medicalClinic.PendingHeals.Any() && medicalClinic.GetBalance() >= medicalClinic.GetTotalCost(),
|
||||||
OnClicked = (button, _) =>
|
OnClicked = (button, _) =>
|
||||||
{
|
{
|
||||||
button.Enabled = false;
|
button.Enabled = false;
|
||||||
@@ -1050,6 +1042,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
CreateUI();
|
CreateUI();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
playerBalanceElement = CampaignUI.UpdateBalanceElement(playerBalanceElement);
|
||||||
|
}
|
||||||
|
|
||||||
refreshTimer += deltaTime;
|
refreshTimer += deltaTime;
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using PlayerBalanceElement = Barotrauma.CampaignUI.PlayerBalanceElement;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -66,12 +67,15 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private Point resolutionWhenCreated;
|
private Point resolutionWhenCreated;
|
||||||
|
|
||||||
|
private PlayerBalanceElement? playerBalanceElement;
|
||||||
|
|
||||||
private Dictionary<ItemPrefab, ItemQuantity> OwnedItems { get; } = new Dictionary<ItemPrefab, ItemQuantity>();
|
private Dictionary<ItemPrefab, ItemQuantity> OwnedItems { get; } = new Dictionary<ItemPrefab, ItemQuantity>();
|
||||||
private Location.StoreInfo ActiveStore { get; set; }
|
private Location.StoreInfo ActiveStore { get; set; }
|
||||||
|
|
||||||
private CargoManager CargoManager => campaignUI.Campaign.CargoManager;
|
private CargoManager CargoManager => campaignUI.Campaign.CargoManager;
|
||||||
private Location CurrentLocation => campaignUI.Campaign.Map?.CurrentLocation;
|
private Location CurrentLocation => campaignUI.Campaign.Map?.CurrentLocation;
|
||||||
private Wallet PlayerWallet => campaignUI.Campaign.Wallet;
|
private int Balance => campaignUI.Campaign.GetBalance();
|
||||||
|
|
||||||
private bool IsBuying => activeTab switch
|
private bool IsBuying => activeTab switch
|
||||||
{
|
{
|
||||||
StoreTab.Buy => true,
|
StoreTab.Buy => true,
|
||||||
@@ -207,7 +211,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (CurrentLocation?.Stores != null)
|
if (CurrentLocation?.Stores != null)
|
||||||
{
|
{
|
||||||
if (CurrentLocation.GetStore(identifier) is { } store)
|
if (!identifier.IsEmpty && CurrentLocation.GetStore(identifier) is { } store)
|
||||||
{
|
{
|
||||||
ActiveStore = store;
|
ActiveStore = store;
|
||||||
if (storeNameBlock != null)
|
if (storeNameBlock != null)
|
||||||
@@ -223,14 +227,45 @@ namespace Barotrauma
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
ActiveStore = null;
|
ActiveStore = null;
|
||||||
string msg = $"Error selecting store with identifier \"{identifier}\" at {CurrentLocation}: store with the identifier doesn't exist at the location.";
|
string errorId, msg;
|
||||||
|
if (identifier.IsEmpty)
|
||||||
|
{
|
||||||
|
errorId = "Store.SelectStore:IdentifierEmpty";
|
||||||
|
msg = $"Error selecting store at {CurrentLocation}: identifier is empty.";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errorId = "Store.SelectStore:StoreDoesntExist";
|
||||||
|
msg = $"Error selecting store with identifier \"{identifier}\" at {CurrentLocation}: store with the identifier doesn't exist at the location.";
|
||||||
|
}
|
||||||
DebugConsole.ShowError(msg);
|
DebugConsole.ShowError(msg);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("Store.SelectStore:StoreDoesntExist", GameAnalyticsManager.ErrorSeverity.Error, msg);
|
GameAnalyticsManager.AddErrorEventOnce(errorId, GameAnalyticsManager.ErrorSeverity.Error, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ActiveStore = null;
|
ActiveStore = null;
|
||||||
|
string errorId = "", msg = "";
|
||||||
|
if (campaignUI.Campaign.Map == null)
|
||||||
|
{
|
||||||
|
errorId = "Store.SelectStore:MapNull";
|
||||||
|
msg = $"Error selecting store with identifier \"{identifier}\": Map is null.";
|
||||||
|
}
|
||||||
|
else if (CurrentLocation == null)
|
||||||
|
{
|
||||||
|
errorId = "Store.SelectStore:CurrentLocationNull";
|
||||||
|
msg = $"Error selecting store with identifier \"{identifier}\": CurrentLocation is null.";
|
||||||
|
}
|
||||||
|
else if (CurrentLocation.Stores == null)
|
||||||
|
{
|
||||||
|
errorId = "Store.SelectStore:StoresNull";
|
||||||
|
msg = $"Error selecting store with identifier \"{identifier}\": CurrentLocation.Stores is null.";
|
||||||
|
}
|
||||||
|
if (!msg.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
DebugConsole.ShowError(msg);
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce(errorId, GameAnalyticsManager.ErrorSeverity.Error, msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
RefreshItemsToSell();
|
RefreshItemsToSell();
|
||||||
Refresh();
|
Refresh();
|
||||||
@@ -615,23 +650,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Player balance ------------------------------------------------
|
// Player balance ------------------------------------------------
|
||||||
var playerBalanceContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.75f / 14.0f), shoppingCrateContent.RectTransform), childAnchor: Anchor.TopRight)
|
playerBalanceElement = CampaignUI.AddBalanceElement(shoppingCrateContent, new Vector2(1.0f, 0.75f / 14.0f));
|
||||||
{
|
|
||||||
RelativeSpacing = 0.005f
|
|
||||||
};
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), playerBalanceContainer.RectTransform),
|
|
||||||
TextManager.Get("campaignstore.balance"), font: GUIStyle.Font, textAlignment: Alignment.BottomRight)
|
|
||||||
{
|
|
||||||
AutoScaleVertical = true,
|
|
||||||
ForceUpperCase = ForceUpperCase.Yes
|
|
||||||
};
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), playerBalanceContainer.RectTransform),
|
|
||||||
"", textColor: Color.White, font: GUIStyle.SubHeadingFont, textAlignment: Alignment.TopRight)
|
|
||||||
{
|
|
||||||
AutoScaleVertical = true,
|
|
||||||
TextScale = 1.1f,
|
|
||||||
TextGetter = GetPlayerBalanceText
|
|
||||||
};
|
|
||||||
|
|
||||||
// Divider ------------------------------------------------
|
// Divider ------------------------------------------------
|
||||||
var dividerFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.6f / 14.0f), shoppingCrateContent.RectTransform), style: null);
|
var dividerFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.6f / 14.0f), shoppingCrateContent.RectTransform), style: null);
|
||||||
@@ -663,7 +682,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
CanBeFocused = false,
|
CanBeFocused = false,
|
||||||
TextScale = 1.1f,
|
TextScale = 1.1f,
|
||||||
TextGetter = () => IsBuying ? GetPlayerBalanceText() : GetMerchantBalanceText()
|
TextGetter = () => IsBuying ? CampaignUI.GetTotalBalance() : GetMerchantBalanceText()
|
||||||
};
|
};
|
||||||
|
|
||||||
var totalContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), shoppingCrateInventoryContainer.RectTransform), isHorizontal: true)
|
var totalContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), shoppingCrateInventoryContainer.RectTransform), isHorizontal: true)
|
||||||
@@ -712,8 +731,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private LocalizedString GetMerchantBalanceText() => TextManager.FormatCurrency(ActiveStore?.Balance ?? 0);
|
private LocalizedString GetMerchantBalanceText() => TextManager.FormatCurrency(ActiveStore?.Balance ?? 0);
|
||||||
|
|
||||||
private LocalizedString GetPlayerBalanceText() => TextManager.FormatCurrency(PlayerWallet.Balance);
|
|
||||||
|
|
||||||
private GUILayoutGroup CreateDealsGroup(GUIListBox parentList, int elementCount)
|
private GUILayoutGroup CreateDealsGroup(GUIListBox parentList, int elementCount)
|
||||||
{
|
{
|
||||||
// Add 1 for the header
|
// Add 1 for the header
|
||||||
@@ -2037,7 +2054,7 @@ namespace Barotrauma
|
|||||||
totalPrice += item.Quantity * ActiveStore.GetAdjustedItemBuyPrice(item.ItemPrefab, priceInfo: priceInfo);
|
totalPrice += item.Quantity * ActiveStore.GetAdjustedItemBuyPrice(item.ItemPrefab, priceInfo: priceInfo);
|
||||||
}
|
}
|
||||||
itemsToRemove.ForEach(i => itemsToPurchase.Remove(i));
|
itemsToRemove.ForEach(i => itemsToPurchase.Remove(i));
|
||||||
if (itemsToPurchase.None() || !PlayerWallet.CanAfford(totalPrice)) { return false; }
|
if (itemsToPurchase.None() || Balance < totalPrice) { return false; }
|
||||||
CargoManager.PurchaseItems(ActiveStore.Identifier, itemsToPurchase, true);
|
CargoManager.PurchaseItems(ActiveStore.Identifier, itemsToPurchase, true);
|
||||||
GameMain.Client?.SendCampaignState();
|
GameMain.Client?.SendCampaignState();
|
||||||
var dialog = new GUIMessageBox(
|
var dialog = new GUIMessageBox(
|
||||||
@@ -2091,7 +2108,7 @@ namespace Barotrauma
|
|||||||
if (IsBuying)
|
if (IsBuying)
|
||||||
{
|
{
|
||||||
shoppingCrateTotal.Text = TextManager.FormatCurrency(buyTotal);
|
shoppingCrateTotal.Text = TextManager.FormatCurrency(buyTotal);
|
||||||
shoppingCrateTotal.TextColor = !PlayerWallet.CanAfford(buyTotal) ? Color.Red : Color.White;
|
shoppingCrateTotal.TextColor = Balance < buyTotal ? Color.Red : Color.White;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2137,7 +2154,7 @@ namespace Barotrauma
|
|||||||
ActiveShoppingCrateList.Content.RectTransform.Children.Any() &&
|
ActiveShoppingCrateList.Content.RectTransform.Children.Any() &&
|
||||||
activeTab switch
|
activeTab switch
|
||||||
{
|
{
|
||||||
StoreTab.Buy => PlayerWallet.CanAfford(buyTotal),
|
StoreTab.Buy => Balance >= buyTotal,
|
||||||
StoreTab.Sell => CurrentLocation != null && sellTotal <= ActiveStore.Balance,
|
StoreTab.Sell => CurrentLocation != null && sellTotal <= ActiveStore.Balance,
|
||||||
StoreTab.SellSub => CurrentLocation != null && sellFromSubTotal <= ActiveStore.Balance,
|
StoreTab.SellSub => CurrentLocation != null && sellFromSubTotal <= ActiveStore.Balance,
|
||||||
_ => false
|
_ => false
|
||||||
@@ -2151,6 +2168,7 @@ namespace Barotrauma
|
|||||||
ActiveShoppingCrateList.Content.RectTransform.Children.Any();
|
ActiveShoppingCrateList.Content.RectTransform.Children.Any();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int prevBalance;
|
||||||
private float ownedItemsUpdateTimer = 0.0f, sellableItemsFromSubUpdateTimer = 0.0f;
|
private float ownedItemsUpdateTimer = 0.0f, sellableItemsFromSubUpdateTimer = 0.0f;
|
||||||
private const float timerUpdateInterval = 1.5f;
|
private const float timerUpdateInterval = 1.5f;
|
||||||
private readonly Stopwatch updateStopwatch = new Stopwatch();
|
private readonly Stopwatch updateStopwatch = new Stopwatch();
|
||||||
@@ -2166,6 +2184,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
playerBalanceElement = CampaignUI.UpdateBalanceElement(playerBalanceElement);
|
||||||
|
|
||||||
// Update the owned items at short intervals and check if the interface should be refreshed
|
// Update the owned items at short intervals and check if the interface should be refreshed
|
||||||
ownedItemsUpdateTimer += deltaTime;
|
ownedItemsUpdateTimer += deltaTime;
|
||||||
if (ownedItemsUpdateTimer >= timerUpdateInterval)
|
if (ownedItemsUpdateTimer >= timerUpdateInterval)
|
||||||
@@ -2202,6 +2222,16 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Refresh the interface if balance changes and the buy tab is open
|
||||||
|
if (activeTab == StoreTab.Buy)
|
||||||
|
{
|
||||||
|
int currBalance = Balance;
|
||||||
|
if (prevBalance != currBalance)
|
||||||
|
{
|
||||||
|
needsBuyingRefresh = true;
|
||||||
|
prevBalance = currBalance;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (needsItemsToSellRefresh)
|
if (needsItemsToSellRefresh)
|
||||||
{
|
{
|
||||||
RefreshItemsToSell();
|
RefreshItemsToSell();
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ using Microsoft.Xna.Framework;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using Microsoft.Xna.Framework.Input;
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
using System.Globalization;
|
||||||
|
using PlayerBalanceElement = Barotrauma.CampaignUI.PlayerBalanceElement;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -31,7 +33,7 @@ namespace Barotrauma
|
|||||||
private readonly List<SubmarineInfo> subsToShow;
|
private readonly List<SubmarineInfo> subsToShow;
|
||||||
private readonly SubmarineDisplayContent[] submarineDisplays = new SubmarineDisplayContent[submarinesPerPage];
|
private readonly SubmarineDisplayContent[] submarineDisplays = new SubmarineDisplayContent[submarinesPerPage];
|
||||||
private SubmarineInfo selectedSubmarine = null;
|
private SubmarineInfo selectedSubmarine = null;
|
||||||
private LocalizedString purchaseAndSwitchText, purchaseOnlyText, deliveryText, currentSubText, deliveryFeeText, priceText, switchText, missingPreviewText, currencyName;
|
private LocalizedString purchaseAndSwitchText, purchaseOnlyText, deliveryText, currentSubText, switchText, missingPreviewText, currencyName;
|
||||||
private readonly RectTransform parent;
|
private readonly RectTransform parent;
|
||||||
private readonly Action closeAction;
|
private readonly Action closeAction;
|
||||||
private Sprite pageIndicator;
|
private Sprite pageIndicator;
|
||||||
@@ -44,6 +46,8 @@ namespace Barotrauma
|
|||||||
private static readonly Color indicatorColor = new Color(112, 149, 129);
|
private static readonly Color indicatorColor = new Color(112, 149, 129);
|
||||||
private Point createdForResolution;
|
private Point createdForResolution;
|
||||||
|
|
||||||
|
private PlayerBalanceElement? playerBalanceElement;
|
||||||
|
|
||||||
private struct SubmarineDisplayContent
|
private struct SubmarineDisplayContent
|
||||||
{
|
{
|
||||||
public GUIFrame background;
|
public GUIFrame background;
|
||||||
@@ -85,12 +89,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
initialized = true;
|
initialized = true;
|
||||||
currentSubText = TextManager.Get("currentsub");
|
currentSubText = TextManager.Get("currentsub");
|
||||||
deliveryFeeText = TextManager.Get("deliveryfee");
|
|
||||||
deliveryText = TextManager.Get("requestdeliverybutton");
|
deliveryText = TextManager.Get("requestdeliverybutton");
|
||||||
switchText = TextManager.Get("switchtosubmarinebutton");
|
switchText = TextManager.Get("switchtosubmarinebutton");
|
||||||
purchaseAndSwitchText = TextManager.Get("purchaseandswitch");
|
purchaseAndSwitchText = TextManager.Get("purchaseandswitch");
|
||||||
purchaseOnlyText = TextManager.Get("purchase");
|
purchaseOnlyText = TextManager.Get("purchase");
|
||||||
priceText = TextManager.Get("price");
|
|
||||||
if (transferService)
|
if (transferService)
|
||||||
{
|
{
|
||||||
deliveryFee = CalculateDeliveryFee();
|
deliveryFee = CalculateDeliveryFee();
|
||||||
@@ -126,10 +128,7 @@ namespace Barotrauma
|
|||||||
content = new GUILayoutGroup(new RectTransform(new Point(background.Rect.Width - HUDLayoutSettings.Padding * 4, background.Rect.Height - HUDLayoutSettings.Padding * 4), background.RectTransform, Anchor.Center)) { AbsoluteSpacing = (int)(HUDLayoutSettings.Padding * 1.5f) };
|
content = new GUILayoutGroup(new RectTransform(new Point(background.Rect.Width - HUDLayoutSettings.Padding * 4, background.Rect.Height - HUDLayoutSettings.Padding * 4), background.RectTransform, Anchor.Center)) { AbsoluteSpacing = (int)(HUDLayoutSettings.Padding * 1.5f) };
|
||||||
GUITextBlock header = new GUITextBlock(new RectTransform(new Vector2(1f, 0.0f), content.RectTransform), transferService ? TextManager.Get("switchsubmarineheader") : TextManager.GetWithVariable("outpostshipyard", "[location]", GameMain.GameSession.Map.CurrentLocation.Name), font: GUIStyle.LargeFont);
|
GUITextBlock header = new GUITextBlock(new RectTransform(new Vector2(1f, 0.0f), content.RectTransform), transferService ? TextManager.Get("switchsubmarineheader") : TextManager.GetWithVariable("outpostshipyard", "[location]", GameMain.GameSession.Map.CurrentLocation.Name), font: GUIStyle.LargeFont);
|
||||||
header.CalculateHeightFromText(0, true);
|
header.CalculateHeightFromText(0, true);
|
||||||
GUITextBlock credits = new GUITextBlock(new RectTransform(Vector2.One, header.RectTransform), "", font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterRight)
|
playerBalanceElement = CampaignUI.AddBalanceElement(header, new Vector2(1.0f, 1.5f));
|
||||||
{
|
|
||||||
TextGetter = CampaignUI.GetMoney
|
|
||||||
};
|
|
||||||
|
|
||||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), content.RectTransform), style: "HorizontalLine");
|
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), content.RectTransform), style: "HorizontalLine");
|
||||||
|
|
||||||
@@ -257,6 +256,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
RefreshSubmarineDisplay(true);
|
RefreshSubmarineDisplay(true);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
playerBalanceElement = CampaignUI.UpdateBalanceElement(playerBalanceElement);
|
||||||
|
}
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
if (PlayerInput.KeyHit(Keys.Left))
|
if (PlayerInput.KeyHit(Keys.Left))
|
||||||
@@ -271,9 +274,22 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void RefreshSubmarineDisplay(bool updateSubs)
|
public void RefreshSubmarineDisplay(bool updateSubs)
|
||||||
{
|
{
|
||||||
if (!initialized) Initialize();
|
if (!initialized)
|
||||||
if (GameMain.GraphicsWidth != createdForResolution.X || GameMain.GraphicsHeight != createdForResolution.Y) CreateGUI();
|
{
|
||||||
if (updateSubs) UpdateSubmarines();
|
Initialize();
|
||||||
|
}
|
||||||
|
if (GameMain.GraphicsWidth != createdForResolution.X || GameMain.GraphicsHeight != createdForResolution.Y)
|
||||||
|
{
|
||||||
|
CreateGUI();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
playerBalanceElement = CampaignUI.UpdateBalanceElement(playerBalanceElement);
|
||||||
|
}
|
||||||
|
if (updateSubs)
|
||||||
|
{
|
||||||
|
UpdateSubmarines();
|
||||||
|
}
|
||||||
|
|
||||||
if (pageIndicators != null)
|
if (pageIndicators != null)
|
||||||
{
|
{
|
||||||
@@ -327,12 +343,12 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
|
|
||||||
submarineDisplays[i].submarineName.Text = subToDisplay.DisplayName;
|
submarineDisplays[i].submarineName.Text = subToDisplay.DisplayName;
|
||||||
submarineDisplays[i].submarineClass.Text = $"{TextManager.GetWithVariable("submarineclass.classsuffixformat", "[type]", TextManager.Get($"submarineclass.{subToDisplay.SubmarineClass}"))}";
|
submarineDisplays[i].submarineClass.Text = TextManager.GetWithVariable("submarineclass.classsuffixformat", "[type]", TextManager.Get($"submarineclass.{subToDisplay.SubmarineClass}"));
|
||||||
|
|
||||||
if (!GameMain.GameSession.IsSubmarineOwned(subToDisplay))
|
if (!GameMain.GameSession.IsSubmarineOwned(subToDisplay))
|
||||||
{
|
{
|
||||||
LocalizedString amountString = TextManager.FormatCurrency(subToDisplay.Price);
|
LocalizedString amountString = TextManager.FormatCurrency(subToDisplay.Price);
|
||||||
submarineDisplays[i].submarineFee.Text = priceText.Replace("[amount]", amountString).Replace("[currencyname]", string.Empty).TrimEnd();
|
submarineDisplays[i].submarineFee.Text = TextManager.GetWithVariable("price", "[amount]", amountString);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -341,7 +357,7 @@ namespace Barotrauma
|
|||||||
if (deliveryFee > 0)
|
if (deliveryFee > 0)
|
||||||
{
|
{
|
||||||
LocalizedString amountString = TextManager.FormatCurrency(deliveryFee);
|
LocalizedString amountString = TextManager.FormatCurrency(deliveryFee);
|
||||||
submarineDisplays[i].submarineFee.Text = deliveryFeeText.Replace("[amount]", amountString).Replace("[currencyname]", string.Empty).TrimEnd();
|
submarineDisplays[i].submarineFee.Text = TextManager.GetWithVariable("deliveryfee", "[amount]", amountString);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -577,7 +593,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void ShowTransferPrompt()
|
private void ShowTransferPrompt()
|
||||||
{
|
{
|
||||||
if (!GameMain.GameSession.Campaign.Wallet.CanAfford(deliveryFee) && deliveryFee > 0)
|
if (!GameMain.GameSession.Campaign.CanAfford(deliveryFee) && deliveryFee > 0)
|
||||||
{
|
{
|
||||||
new GUIMessageBox(TextManager.Get("deliveryrequestheader"), TextManager.GetWithVariables("notenoughmoneyfordeliverytext",
|
new GUIMessageBox(TextManager.Get("deliveryrequestheader"), TextManager.GetWithVariables("notenoughmoneyfordeliverytext",
|
||||||
("[currencyname]", currencyName),
|
("[currencyname]", currencyName),
|
||||||
@@ -625,7 +641,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void ShowBuyPrompt(bool purchaseOnly)
|
private void ShowBuyPrompt(bool purchaseOnly)
|
||||||
{
|
{
|
||||||
if (!GameMain.GameSession.Campaign.Wallet.CanAfford(selectedSubmarine.Price))
|
if (!GameMain.GameSession.Campaign.CanAfford(selectedSubmarine.Price))
|
||||||
{
|
{
|
||||||
new GUIMessageBox(TextManager.Get("purchasesubmarineheader"), TextManager.GetWithVariables("notenoughmoneyforpurchasetext",
|
new GUIMessageBox(TextManager.Get("purchasesubmarineheader"), TextManager.GetWithVariables("notenoughmoneyforpurchasetext",
|
||||||
("[currencyname]", currencyName),
|
("[currencyname]", currencyName),
|
||||||
|
|||||||
@@ -698,6 +698,12 @@ namespace Barotrauma
|
|||||||
Color = Color.Transparent
|
Color = Color.Transparent
|
||||||
};
|
};
|
||||||
|
|
||||||
|
frame.OnSecondaryClicked += (component, data) =>
|
||||||
|
{
|
||||||
|
NetLobbyScreen.CreateModerationContextMenu(client);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), frame.RectTransform, Anchor.Center), isHorizontal: true)
|
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), frame.RectTransform, Anchor.Center), isHorizontal: true)
|
||||||
{
|
{
|
||||||
AbsoluteSpacing = 2
|
AbsoluteSpacing = 2
|
||||||
@@ -1057,7 +1063,7 @@ namespace Barotrauma
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasMoneyPermissions = campaign.AllowedToManageCampaign(ClientPermissions.ManageMoney);
|
bool hasMoneyPermissions = CampaignMode.AllowedToManageWallets();
|
||||||
salarySlider.Enabled = hasMoneyPermissions;
|
salarySlider.Enabled = hasMoneyPermissions;
|
||||||
Wallet otherWallet;
|
Wallet otherWallet;
|
||||||
|
|
||||||
@@ -1402,6 +1408,12 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void CreateMissionInfo(GUIFrame infoFrame)
|
private void CreateMissionInfo(GUIFrame infoFrame)
|
||||||
{
|
{
|
||||||
|
if (Level.Loaded?.LevelData == null)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Failed to display mission info in the tab menu (no level loaded).\n" + Environment.StackTrace);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
infoFrame.ClearChildren();
|
infoFrame.ClearChildren();
|
||||||
GUIFrame missionFrame = new GUIFrame(new RectTransform(Vector2.One, infoFrame.RectTransform, Anchor.TopCenter), style: "GUIFrameListBox");
|
GUIFrame missionFrame = new GUIFrame(new RectTransform(Vector2.One, infoFrame.RectTransform, Anchor.TopCenter), style: "GUIFrameListBox");
|
||||||
int padding = (int)(0.0245f * missionFrame.Rect.Height);
|
int padding = (int)(0.0245f * missionFrame.Rect.Height);
|
||||||
@@ -2016,7 +2028,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
parent.Content.ClearChildren();
|
parent.Content.ClearChildren();
|
||||||
List<GUITextBlock> skillNames = new List<GUITextBlock>();
|
List<GUITextBlock> skillNames = new List<GUITextBlock>();
|
||||||
foreach (Skill skill in character.Info.Job.Skills)
|
foreach (Skill skill in character.Info.Job.GetSkills())
|
||||||
{
|
{
|
||||||
GUILayoutGroup skillContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.2f), parent.Content.RectTransform), isHorizontal: true) { CanBeFocused = false };
|
GUILayoutGroup skillContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.2f), parent.Content.RectTransform), isHorizontal: true) { CanBeFocused = false };
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ using FarseerPhysics;
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using Microsoft.Xna.Framework.Input;
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
using PlayerBalanceElement = Barotrauma.CampaignUI.PlayerBalanceElement;
|
||||||
|
|
||||||
// ReSharper disable UnusedVariable
|
// ReSharper disable UnusedVariable
|
||||||
|
|
||||||
@@ -41,7 +42,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private readonly CampaignUI campaignUI;
|
private readonly CampaignUI campaignUI;
|
||||||
private CampaignMode? Campaign => campaignUI.Campaign;
|
private CampaignMode? Campaign => campaignUI.Campaign;
|
||||||
private Wallet PlayerWallet => Campaign?.Wallet ?? Wallet.Invalid;
|
private int PlayerBalance => Campaign?.GetBalance() ?? 0;
|
||||||
private UpgradeTab selectedUpgradeTab = UpgradeTab.Upgrade;
|
private UpgradeTab selectedUpgradeTab = UpgradeTab.Upgrade;
|
||||||
|
|
||||||
private GUIMessageBox? currectConfirmation;
|
private GUIMessageBox? currectConfirmation;
|
||||||
@@ -75,6 +76,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private bool needsRefresh = true;
|
private bool needsRefresh = true;
|
||||||
|
|
||||||
|
private PlayerBalanceElement? playerBalanceElement;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// While set to true any call to <see cref="RefreshUpgradeList"/> will cause the buy button to be disabled and to not update the prices.
|
/// While set to true any call to <see cref="RefreshUpgradeList"/> will cause the buy button to be disabled and to not update the prices.
|
||||||
/// This is to prevent us from buying another upgrade before the server has given us the new prices and causing potential syncing issues.
|
/// This is to prevent us from buying another upgrade before the server has given us the new prices and causing potential syncing issues.
|
||||||
@@ -293,9 +296,14 @@ namespace Barotrauma
|
|||||||
* |---------------------------------------------------------------------------------------------------|
|
* |---------------------------------------------------------------------------------------------------|
|
||||||
*/
|
*/
|
||||||
GUILayoutGroup rightLayout = new GUILayoutGroup(rectT(0.5f, 1, topHeaderLayout), childAnchor: Anchor.TopRight);
|
GUILayoutGroup rightLayout = new GUILayoutGroup(rectT(0.5f, 1, topHeaderLayout), childAnchor: Anchor.TopRight);
|
||||||
GUILayoutGroup priceLayout = new GUILayoutGroup(rectT(1, 0.8f, rightLayout), childAnchor: Anchor.Center) { RelativeSpacing = 0.08f };
|
playerBalanceElement = CampaignUI.AddBalanceElement(rightLayout, new Vector2(1.0f, 0.8f));
|
||||||
new GUITextBlock(rectT(1f, 0f, priceLayout), TextManager.Get("CampaignStore.Balance"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right);
|
if (playerBalanceElement is { } balanceElement)
|
||||||
new GUITextBlock(rectT(1f, 0f, priceLayout), TextManager.FormatCurrency(PlayerWallet.Balance), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right) { TextGetter = () => TextManager.FormatCurrency(PlayerWallet.Balance) };
|
{
|
||||||
|
balanceElement.TotalBalanceContainer.OnAddedToGUIUpdateList += (_) =>
|
||||||
|
{
|
||||||
|
playerBalanceElement = CampaignUI.UpdateBalanceElement(playerBalanceElement);
|
||||||
|
};
|
||||||
|
}
|
||||||
new GUIFrame(rectT(0.5f, 0.1f, rightLayout, Anchor.BottomRight), style: "HorizontalLine") { IgnoreLayoutGroups = true };
|
new GUIFrame(rectT(0.5f, 0.1f, rightLayout, Anchor.BottomRight), style: "HorizontalLine") { IgnoreLayoutGroups = true };
|
||||||
|
|
||||||
repairButton.OnClicked = upgradeButton.OnClicked = (button, o) =>
|
repairButton.OnClicked = upgradeButton.OnClicked = (button, o) =>
|
||||||
@@ -435,14 +443,14 @@ namespace Barotrauma
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PlayerWallet.CanAfford(hullRepairCost))
|
if (PlayerBalance >= hullRepairCost)
|
||||||
{
|
{
|
||||||
LocalizedString body = TextManager.GetWithVariable("WallRepairs.PurchasePromptBody", "[amount]", hullRepairCost.ToString());
|
LocalizedString body = TextManager.GetWithVariable("WallRepairs.PurchasePromptBody", "[amount]", hullRepairCost.ToString());
|
||||||
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
|
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
|
||||||
{
|
{
|
||||||
if (PlayerWallet.Balance >= hullRepairCost)
|
if (PlayerBalance >= hullRepairCost)
|
||||||
{
|
{
|
||||||
PlayerWallet.TryDeduct(hullRepairCost);
|
Campaign.TryPurchase(null, hullRepairCost);
|
||||||
GameAnalyticsManager.AddMoneySpentEvent(hullRepairCost, GameAnalyticsManager.MoneySink.Service, "hullrepairs");
|
GameAnalyticsManager.AddMoneySpentEvent(hullRepairCost, GameAnalyticsManager.MoneySink.Service, "hullrepairs");
|
||||||
Campaign.PurchasedHullRepairs = true;
|
Campaign.PurchasedHullRepairs = true;
|
||||||
button.Enabled = false;
|
button.Enabled = false;
|
||||||
@@ -470,14 +478,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
CreateRepairEntry(currentStoreLayout.Content, TextManager.Get("repairallitems"), "RepairItemsButton", itemRepairCost, (button, o) =>
|
CreateRepairEntry(currentStoreLayout.Content, TextManager.Get("repairallitems"), "RepairItemsButton", itemRepairCost, (button, o) =>
|
||||||
{
|
{
|
||||||
if (PlayerWallet.Balance >= itemRepairCost && !Campaign.PurchasedItemRepairs)
|
if (PlayerBalance >= itemRepairCost && !Campaign.PurchasedItemRepairs)
|
||||||
{
|
{
|
||||||
LocalizedString body = TextManager.GetWithVariable("ItemRepairs.PurchasePromptBody", "[amount]", itemRepairCost.ToString());
|
LocalizedString body = TextManager.GetWithVariable("ItemRepairs.PurchasePromptBody", "[amount]", itemRepairCost.ToString());
|
||||||
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
|
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
|
||||||
{
|
{
|
||||||
if (PlayerWallet.Balance >= itemRepairCost && !Campaign.PurchasedItemRepairs)
|
if (PlayerBalance >= itemRepairCost && !Campaign.PurchasedItemRepairs)
|
||||||
{
|
{
|
||||||
PlayerWallet.TryDeduct(itemRepairCost);
|
Campaign.TryPurchase(null, itemRepairCost);
|
||||||
GameAnalyticsManager.AddMoneySpentEvent(hullRepairCost, GameAnalyticsManager.MoneySink.Service, "devicerepairs");
|
GameAnalyticsManager.AddMoneySpentEvent(hullRepairCost, GameAnalyticsManager.MoneySink.Service, "devicerepairs");
|
||||||
Campaign.PurchasedItemRepairs = true;
|
Campaign.PurchasedItemRepairs = true;
|
||||||
button.Enabled = false;
|
button.Enabled = false;
|
||||||
@@ -516,14 +524,14 @@ namespace Barotrauma
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PlayerWallet.CanAfford(shuttleRetrieveCost) && !Campaign.PurchasedLostShuttles)
|
if (PlayerBalance >= shuttleRetrieveCost && !Campaign.PurchasedLostShuttles)
|
||||||
{
|
{
|
||||||
LocalizedString body = TextManager.GetWithVariable("ReplaceLostShuttles.PurchasePromptBody", "[amount]", shuttleRetrieveCost.ToString());
|
LocalizedString body = TextManager.GetWithVariable("ReplaceLostShuttles.PurchasePromptBody", "[amount]", shuttleRetrieveCost.ToString());
|
||||||
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
|
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
|
||||||
{
|
{
|
||||||
if (PlayerWallet.Balance >= shuttleRetrieveCost && !Campaign.PurchasedLostShuttles)
|
if (PlayerBalance >= shuttleRetrieveCost && !Campaign.PurchasedLostShuttles)
|
||||||
{
|
{
|
||||||
PlayerWallet.TryDeduct(shuttleRetrieveCost);
|
Campaign.TryPurchase(null, shuttleRetrieveCost);
|
||||||
GameAnalyticsManager.AddMoneySpentEvent(hullRepairCost, GameAnalyticsManager.MoneySink.Service, "retrieveshuttle");
|
GameAnalyticsManager.AddMoneySpentEvent(hullRepairCost, GameAnalyticsManager.MoneySink.Service, "retrieveshuttle");
|
||||||
Campaign.PurchasedLostShuttles = true;
|
Campaign.PurchasedLostShuttles = true;
|
||||||
button.Enabled = false;
|
button.Enabled = false;
|
||||||
@@ -581,13 +589,13 @@ namespace Barotrauma
|
|||||||
new GUITextBlock(rectT(1, 0, textLayout), title, font: GUIStyle.SubHeadingFont) { CanBeFocused = false, AutoScaleHorizontal = true };
|
new GUITextBlock(rectT(1, 0, textLayout), title, font: GUIStyle.SubHeadingFont) { CanBeFocused = false, AutoScaleHorizontal = true };
|
||||||
new GUITextBlock(rectT(1, 0, textLayout), TextManager.FormatCurrency(price));
|
new GUITextBlock(rectT(1, 0, textLayout), TextManager.FormatCurrency(price));
|
||||||
GUILayoutGroup buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, contentLayout), childAnchor: Anchor.Center) { UserData = "buybutton" };
|
GUILayoutGroup buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, contentLayout), childAnchor: Anchor.Center) { UserData = "buybutton" };
|
||||||
new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: "RepairBuyButton") { ClickSound = GUISoundType.HireRepairClick, Enabled = PlayerWallet.Balance >= price && !isDisabled, OnClicked = onPressed };
|
new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: "RepairBuyButton") { ClickSound = GUISoundType.HireRepairClick, Enabled = PlayerBalance >= price && !isDisabled, OnClicked = onPressed };
|
||||||
contentLayout.Recalculate();
|
contentLayout.Recalculate();
|
||||||
buyButtonLayout.Recalculate();
|
buyButtonLayout.Recalculate();
|
||||||
|
|
||||||
if (disableElement)
|
if (disableElement)
|
||||||
{
|
{
|
||||||
frameChild.Enabled = PlayerWallet.Balance >= price && !isDisabled;
|
frameChild.Enabled = PlayerBalance >= price && !isDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!HasPermission)
|
if (!HasPermission)
|
||||||
@@ -972,7 +980,7 @@ namespace Barotrauma
|
|||||||
buttonStyle: isPurchased ? "WeaponInstallButton" : "StoreAddToCrateButton"));
|
buttonStyle: isPurchased ? "WeaponInstallButton" : "StoreAddToCrateButton"));
|
||||||
|
|
||||||
if (!(frames.Last().FindChild(c => c is GUIButton, recursive: true) is GUIButton buyButton)) { continue; }
|
if (!(frames.Last().FindChild(c => c is GUIButton, recursive: true) is GUIButton buyButton)) { continue; }
|
||||||
if (PlayerWallet.CanAfford(price))
|
if (PlayerBalance >= price)
|
||||||
{
|
{
|
||||||
buyButton.Enabled = true;
|
buyButton.Enabled = true;
|
||||||
buyButton.OnClicked += (button, o) =>
|
buyButton.OnClicked += (button, o) =>
|
||||||
@@ -1602,7 +1610,7 @@ namespace Barotrauma
|
|||||||
if (button != null)
|
if (button != null)
|
||||||
{
|
{
|
||||||
button.Enabled = currentLevel < prefab.MaxLevel;
|
button.Enabled = currentLevel < prefab.MaxLevel;
|
||||||
if (WaitForServerUpdate || !campaign.Wallet.CanAfford(price))
|
if (WaitForServerUpdate || campaign.GetBalance() < price)
|
||||||
{
|
{
|
||||||
button.Enabled = false;
|
button.Enabled = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -671,6 +671,8 @@ namespace Barotrauma
|
|||||||
if (!TitleScreen.PlayingSplashScreen)
|
if (!TitleScreen.PlayingSplashScreen)
|
||||||
{
|
{
|
||||||
SoundPlayer.Update((float)Timing.Step);
|
SoundPlayer.Update((float)Timing.Step);
|
||||||
|
GUI.ClearUpdateList();
|
||||||
|
GUI.UpdateGUIMessageBoxesOnly((float)Timing.Step);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen &&
|
if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen &&
|
||||||
@@ -1117,10 +1119,10 @@ namespace Barotrauma
|
|||||||
var msgBox = new GUIMessageBox(TextManager.Get("EditorDisclaimerTitle"), TextManager.Get("EditorDisclaimerText"));
|
var msgBox = new GUIMessageBox(TextManager.Get("EditorDisclaimerTitle"), TextManager.Get("EditorDisclaimerText"));
|
||||||
var linkHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), msgBox.Content.RectTransform)) { Stretch = true, RelativeSpacing = 0.025f };
|
var linkHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), msgBox.Content.RectTransform)) { Stretch = true, RelativeSpacing = 0.025f };
|
||||||
linkHolder.RectTransform.MaxSize = new Point(int.MaxValue, linkHolder.Rect.Height);
|
linkHolder.RectTransform.MaxSize = new Point(int.MaxValue, linkHolder.Rect.Height);
|
||||||
List<(LocalizedString Caption, LocalizedString Url)> links = new List<(LocalizedString, LocalizedString)>()
|
List<(LocalizedString Caption, string Url)> links = new List<(LocalizedString, string)>()
|
||||||
{
|
{
|
||||||
(TextManager.Get("EditorDisclaimerWikiLink"), TextManager.Get("EditorDisclaimerWikiUrl")),
|
(TextManager.Get("EditorDisclaimerWikiLink"), TextManager.Get("EditorDisclaimerWikiUrl").Fallback("https://barotraumagame.com/wiki").Value),
|
||||||
(TextManager.Get("EditorDisclaimerDiscordLink"), TextManager.Get("EditorDisclaimerDiscordUrl")),
|
(TextManager.Get("EditorDisclaimerDiscordLink"), TextManager.Get("EditorDisclaimerDiscordUrl").Fallback("https://discordapp.com/invite/undertow").Value),
|
||||||
};
|
};
|
||||||
foreach (var link in links)
|
foreach (var link in links)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Microsoft.Xna.Framework;
|
|||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
@@ -28,6 +29,8 @@ namespace Barotrauma
|
|||||||
protected GUIFrame campaignUIContainer;
|
protected GUIFrame campaignUIContainer;
|
||||||
public CampaignUI CampaignUI;
|
public CampaignUI CampaignUI;
|
||||||
|
|
||||||
|
public static CancellationTokenSource StartRoundCancellationToken { get; private set; }
|
||||||
|
|
||||||
public bool ForceMapUI
|
public bool ForceMapUI
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
@@ -99,6 +102,16 @@ namespace Barotrauma
|
|||||||
GameMain.Client.ConnectedClients.None(c => c.InGame && (c.IsOwner || c.HasPermission(permissions)));
|
GameMain.Client.ConnectedClients.None(c => c.InGame && (c.IsOwner || c.HasPermission(permissions)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool AllowedToManageWallets()
|
||||||
|
{
|
||||||
|
if (GameMain.Client == null) { return true; }
|
||||||
|
|
||||||
|
return
|
||||||
|
GameMain.Client.HasPermission(ClientPermissions.ManageMoney) ||
|
||||||
|
GameMain.Client.HasPermission(ClientPermissions.ManageCampaign) ||
|
||||||
|
GameMain.Client.IsServerOwner;
|
||||||
|
}
|
||||||
|
|
||||||
public override void Draw(SpriteBatch spriteBatch)
|
public override void Draw(SpriteBatch spriteBatch)
|
||||||
{
|
{
|
||||||
if (overlayColor.A > 0)
|
if (overlayColor.A > 0)
|
||||||
@@ -245,10 +258,11 @@ namespace Barotrauma
|
|||||||
|
|
||||||
GUI.ClearCursorWait();
|
GUI.ClearCursorWait();
|
||||||
|
|
||||||
|
StartRoundCancellationToken = new CancellationTokenSource();
|
||||||
var loadTask = Task.Run(async () =>
|
var loadTask = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
await Task.Yield();
|
await Task.Yield();
|
||||||
Rand.ThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
|
Rand.ThreadId = Thread.CurrentThread.ManagedThreadId;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
GameMain.GameSession.StartRound(newLevel, mirrorLevel: mirror);
|
GameMain.GameSession.StartRound(newLevel, mirrorLevel: mirror);
|
||||||
@@ -258,7 +272,7 @@ namespace Barotrauma
|
|||||||
roundSummaryScreen.LoadException = e;
|
roundSummaryScreen.LoadException = e;
|
||||||
}
|
}
|
||||||
Rand.ThreadId = 0;
|
Rand.ThreadId = 0;
|
||||||
});
|
}, StartRoundCancellationToken.Token);
|
||||||
TaskPool.Add("AsyncCampaignStartRound", loadTask, (t) =>
|
TaskPool.Add("AsyncCampaignStartRound", loadTask, (t) =>
|
||||||
{
|
{
|
||||||
overlayColor = Color.Transparent;
|
overlayColor = Color.Transparent;
|
||||||
|
|||||||
@@ -37,6 +37,16 @@ namespace Barotrauma
|
|||||||
public Wallet PersonalWallet => Character.Controlled?.Wallet ?? Wallet.Invalid;
|
public Wallet PersonalWallet => Character.Controlled?.Wallet ?? Wallet.Invalid;
|
||||||
public override Wallet Wallet => GetWallet();
|
public override Wallet Wallet => GetWallet();
|
||||||
|
|
||||||
|
public override int GetBalance(Client client = null)
|
||||||
|
{
|
||||||
|
if (!AllowedToManageWallets())
|
||||||
|
{
|
||||||
|
return PersonalWallet.Balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PersonalWallet.Balance + Bank.Balance;
|
||||||
|
}
|
||||||
|
|
||||||
public override Wallet GetWallet(Client client = null)
|
public override Wallet GetWallet(Client client = null)
|
||||||
{
|
{
|
||||||
return PersonalWallet;
|
return PersonalWallet;
|
||||||
@@ -913,6 +923,31 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool TryPurchase(Client client, int price)
|
||||||
|
{
|
||||||
|
if (!AllowedToManageCampaign(ClientPermissions.ManageCampaign))
|
||||||
|
{
|
||||||
|
return PersonalWallet.TryDeduct(price);
|
||||||
|
}
|
||||||
|
|
||||||
|
int balance = PersonalWallet.Balance;
|
||||||
|
|
||||||
|
if (balance >= price)
|
||||||
|
{
|
||||||
|
return PersonalWallet.TryDeduct(price);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (balance + Bank.Balance >= price)
|
||||||
|
{
|
||||||
|
int remainder = price - balance;
|
||||||
|
if (balance > 0) { PersonalWallet.Deduct(balance); }
|
||||||
|
Bank.Deduct(remainder);
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public override void Save(XElement element)
|
public override void Save(XElement element)
|
||||||
{
|
{
|
||||||
//do nothing, the clients get the save files from the server
|
//do nothing, the clients get the save files from the server
|
||||||
|
|||||||
@@ -56,10 +56,9 @@ namespace Barotrauma.Items.Components
|
|||||||
ContentXElement spriteElement = limbElement.GetChildElement("sprite");
|
ContentXElement spriteElement = limbElement.GetChildElement("sprite");
|
||||||
if (spriteElement == null) { continue; }
|
if (spriteElement == null) { continue; }
|
||||||
|
|
||||||
string spritePath = spriteElement.GetAttribute("texture").Value;
|
ContentPath contentPath = spriteElement.GetAttributeContentPath("texture");
|
||||||
|
|
||||||
spritePath = characterInfo.ReplaceVars(spritePath);
|
|
||||||
|
|
||||||
|
string spritePath = characterInfo.ReplaceVars(contentPath.Value);
|
||||||
string fileName = Path.GetFileNameWithoutExtension(spritePath);
|
string fileName = Path.GetFileNameWithoutExtension(spritePath);
|
||||||
|
|
||||||
//go through the files in the directory to find a matching sprite
|
//go through the files in the directory to find a matching sprite
|
||||||
|
|||||||
@@ -584,18 +584,15 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
availableCharge = 0.0f;
|
availableCharge = 0.0f;
|
||||||
availableCapacity = 0.0f;
|
availableCapacity = 0.0f;
|
||||||
if (item.Connections == null) { return; }
|
if (item.Connections == null || powerIn == null) { return; }
|
||||||
foreach (Connection c in item.Connections)
|
var recipients = powerIn.Recipients;
|
||||||
|
foreach (Connection recipient in recipients)
|
||||||
{
|
{
|
||||||
var recipients = c.Recipients;
|
if (!recipient.IsPower || !recipient.IsOutput) { continue; }
|
||||||
foreach (Connection recipient in recipients)
|
var battery = recipient.Item?.GetComponent<PowerContainer>();
|
||||||
{
|
if (battery == null || battery.Item.Condition <= 0.0f) { continue; }
|
||||||
if (!recipient.IsPower || !recipient.IsOutput) { continue; }
|
availableCharge += battery.Charge;
|
||||||
var battery = recipient.Item?.GetComponent<PowerContainer>();
|
availableCapacity += battery.Capacity;
|
||||||
if (battery == null) { continue; }
|
|
||||||
availableCharge += battery.Charge;
|
|
||||||
availableCapacity += battery.Capacity;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -273,10 +273,16 @@ namespace Barotrauma
|
|||||||
foreach (string tag in readTags)
|
foreach (string tag in readTags)
|
||||||
{
|
{
|
||||||
string[] s = tag.Split(':');
|
string[] s = tag.Split(':');
|
||||||
if (s[0] == "name")
|
switch (s[0])
|
||||||
idName = s[1];
|
{
|
||||||
if (s[0] == "job")
|
case "name":
|
||||||
idJob = s[1];
|
idName = s[1];
|
||||||
|
break;
|
||||||
|
case "job":
|
||||||
|
case "jobid":
|
||||||
|
idJob = s[1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (idName != null)
|
if (idName != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1550,9 +1550,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
DebugConsole.Log($"Received entity spawn message for item \"{itemName}\" (identifier: {itemIdentifier}, id: {itemId})");
|
DebugConsole.Log($"Received entity spawn message for item \"{itemName}\" (identifier: {itemIdentifier}, id: {itemId})");
|
||||||
|
|
||||||
var itemPrefab = string.IsNullOrEmpty(itemIdentifier) ?
|
ItemPrefab itemPrefab =
|
||||||
MapEntityPrefab.Find(itemName, null, showErrorMessages: false) as ItemPrefab :
|
string.IsNullOrEmpty(itemIdentifier) ?
|
||||||
MapEntityPrefab.Find(itemName, itemIdentifier, showErrorMessages: false) as ItemPrefab;
|
ItemPrefab.Find(itemName, Identifier.Empty) :
|
||||||
|
ItemPrefab.Find(itemName, itemIdentifier.ToIdentifier());
|
||||||
|
|
||||||
Vector2 pos = Vector2.Zero;
|
Vector2 pos = Vector2.Zero;
|
||||||
Submarine sub = null;
|
Submarine sub = null;
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
foreach ((Identifier identifier, Rectangle rect) in DisplayEntities)
|
foreach ((Identifier identifier, Rectangle rect) in DisplayEntities)
|
||||||
{
|
{
|
||||||
var entityPrefab = MapEntityPrefab.FindByIdentifier(identifier);
|
var entityPrefab = FindByIdentifier(identifier);
|
||||||
if (entityPrefab is CoreEntityPrefab) { continue; }
|
if (entityPrefab is CoreEntityPrefab || entityPrefab == null) { continue; }
|
||||||
var drawRect = new Rectangle(
|
var drawRect = new Rectangle(
|
||||||
(int)(rect.X * scale) + drawArea.Center.X, (int)((rect.Y) * scale) - drawArea.Center.Y,
|
(int)(rect.X * scale) + drawArea.Center.X, (int)((rect.Y) * scale) - drawArea.Center.Y,
|
||||||
(int)(rect.Width * scale), (int)(rect.Height * scale));
|
(int)(rect.Width * scale), (int)(rect.Height * scale));
|
||||||
@@ -32,11 +32,10 @@ namespace Barotrauma
|
|||||||
base.DrawPlacing(spriteBatch, cam);
|
base.DrawPlacing(spriteBatch, cam);
|
||||||
foreach ((Identifier identifier, Rectangle rect) in DisplayEntities)
|
foreach ((Identifier identifier, Rectangle rect) in DisplayEntities)
|
||||||
{
|
{
|
||||||
var entityPrefab = MapEntityPrefab.Find(p => p.Identifier == identifier);
|
var entityPrefab = FindByIdentifier(identifier);
|
||||||
|
if (entityPrefab == null) { continue; }
|
||||||
Rectangle drawRect = rect;
|
Rectangle drawRect = rect;
|
||||||
|
|
||||||
drawRect.Location += placePosition != Vector2.Zero ? placePosition.ToPoint() : Submarine.MouseToWorldGrid(cam, Submarine.MainSub).ToPoint();
|
drawRect.Location += placePosition != Vector2.Zero ? placePosition.ToPoint() : Submarine.MouseToWorldGrid(cam, Submarine.MainSub).ToPoint();
|
||||||
|
|
||||||
entityPrefab.DrawPlacing(spriteBatch, drawRect, entityPrefab.Scale);
|
entityPrefab.DrawPlacing(spriteBatch, drawRect, entityPrefab.Scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
using Barotrauma.IO;
|
using System;
|
||||||
|
using Barotrauma.IO;
|
||||||
using Barotrauma.Items.Components;
|
using Barotrauma.Items.Components;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using Microsoft.Xna.Framework.Input;
|
using Microsoft.Xna.Framework.Input;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
using Barotrauma.Extensions;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -107,6 +109,25 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
var pathContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform), isHorizontal: true);
|
var pathContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform), isHorizontal: true);
|
||||||
|
|
||||||
|
string filePath = this.filePath;
|
||||||
|
if (filePath.StartsWith("Submarines"))
|
||||||
|
{
|
||||||
|
//this is the old submarines path, try to find a local mod that has a submarine with this name
|
||||||
|
string subName = Path.GetFileNameWithoutExtension(filePath);
|
||||||
|
string foundPath = ContentPackageManager.LocalPackages.Concat(ContentPackageManager.VanillaCorePackage.ToEnumerable())
|
||||||
|
.SelectMany(p => p.GetFiles<SubmarineFile>())
|
||||||
|
.FirstOrDefault(f => Path.GetFileNameWithoutExtension(f.Path.Value).Equals(subName, StringComparison.OrdinalIgnoreCase))
|
||||||
|
?.Path.Value;
|
||||||
|
if (foundPath.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
//no such sub found among the local mods, just guess the correct path
|
||||||
|
foundPath = Path.Combine(ContentPackage.LocalModsDir, subName, $"{subName}.sub");
|
||||||
|
}
|
||||||
|
|
||||||
|
filePath = foundPath;
|
||||||
|
}
|
||||||
|
|
||||||
var pathBox = new GUITextBox(new RectTransform(new Vector2(0.75f, 1.0f), pathContainer.RectTransform), filePath, font: GUIStyle.SmallFont);
|
var pathBox = new GUITextBox(new RectTransform(new Vector2(0.75f, 1.0f), pathContainer.RectTransform), filePath, font: GUIStyle.SmallFont);
|
||||||
var reloadButton = new GUIButton(new RectTransform(new Vector2(0.25f / pathBox.RectTransform.RelativeSize.X, 1.0f), pathBox.RectTransform, Anchor.CenterRight, Pivot.CenterLeft),
|
var reloadButton = new GUIButton(new RectTransform(new Vector2(0.25f / pathBox.RectTransform.RelativeSize.X, 1.0f), pathBox.RectTransform, Anchor.CenterRight, Pivot.CenterLeft),
|
||||||
TextManager.Get("ReloadLinkedSub"), style: "GUIButtonSmall")
|
TextManager.Get("ReloadLinkedSub"), style: "GUIButtonSmall")
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace Barotrauma
|
|||||||
visibleSubs.Clear();
|
visibleSubs.Clear();
|
||||||
foreach (Submarine sub in Loaded)
|
foreach (Submarine sub in Loaded)
|
||||||
{
|
{
|
||||||
if (sub.WorldPosition.Y < Level.MaxEntityDepth) { continue; }
|
if (Level.Loaded != null && sub.WorldPosition.Y < Level.MaxEntityDepth) { continue; }
|
||||||
|
|
||||||
int margin = 500;
|
int margin = 500;
|
||||||
Rectangle worldBorders = new Rectangle(
|
Rectangle worldBorders = new Rectangle(
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ namespace Barotrauma.Networking
|
|||||||
VoipSound = null;
|
VoipSound = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetPermissions(ClientPermissions permissions, List<string> permittedConsoleCommands)
|
public void SetPermissions(ClientPermissions permissions, IEnumerable<string> permittedConsoleCommands)
|
||||||
{
|
{
|
||||||
List<DebugConsole.Command> permittedCommands = new List<DebugConsole.Command>();
|
List<DebugConsole.Command> permittedCommands = new List<DebugConsole.Command>();
|
||||||
foreach (string commandName in permittedConsoleCommands)
|
foreach (string commandName in permittedConsoleCommands)
|
||||||
@@ -92,14 +92,18 @@ namespace Barotrauma.Networking
|
|||||||
SetPermissions(permissions, permittedCommands);
|
SetPermissions(permissions, permittedCommands);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetPermissions(ClientPermissions permissions, List<DebugConsole.Command> permittedConsoleCommands)
|
public void SetPermissions(ClientPermissions permissions, IEnumerable<DebugConsole.Command> permittedConsoleCommands)
|
||||||
{
|
{
|
||||||
if (GameMain.Client == null)
|
if (GameMain.Client == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Permissions = permissions;
|
Permissions = permissions;
|
||||||
PermittedConsoleCommands.Clear(); PermittedConsoleCommands.AddRange(permittedConsoleCommands);
|
PermittedConsoleCommands.Clear();
|
||||||
|
foreach (var command in permittedConsoleCommands)
|
||||||
|
{
|
||||||
|
PermittedConsoleCommands.Add(command);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GivePermission(ClientPermissions permission)
|
public void GivePermission(ClientPermissions permission)
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
using Barotrauma.Items.Components;
|
using Barotrauma.Items.Components;
|
||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
partial class EntitySpawner : Entity, IServerSerializable
|
partial class EntitySpawner : Entity, IServerSerializable
|
||||||
{
|
{
|
||||||
|
public readonly List<(Entity entity, bool isRemoval)> receivedEvents = new List<(Entity entity, bool isRemoval)>();
|
||||||
|
|
||||||
public void ClientEventRead(IReadMessage message, float sendingTime)
|
public void ClientEventRead(IReadMessage message, float sendingTime)
|
||||||
{
|
{
|
||||||
bool remove = message.ReadBoolean();
|
bool remove = message.ReadBoolean();
|
||||||
@@ -12,7 +15,6 @@ namespace Barotrauma
|
|||||||
if (remove)
|
if (remove)
|
||||||
{
|
{
|
||||||
ushort entityId = message.ReadUInt16();
|
ushort entityId = message.ReadUInt16();
|
||||||
|
|
||||||
var entity = FindEntityByID(entityId);
|
var entity = FindEntityByID(entityId);
|
||||||
if (entity != null)
|
if (entity != null)
|
||||||
{
|
{
|
||||||
@@ -27,6 +29,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
DebugConsole.Log("Received entity removal message for ID " + entityId + ". Entity with a matching ID not found.");
|
DebugConsole.Log("Received entity removal message for ID " + entityId + ". Entity with a matching ID not found.");
|
||||||
}
|
}
|
||||||
|
receivedEvents.Add((entity, true));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -34,13 +37,29 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
case (byte)SpawnableType.Item:
|
case (byte)SpawnableType.Item:
|
||||||
var newItem = Item.ReadSpawnData(message, true);
|
var newItem = Item.ReadSpawnData(message, true);
|
||||||
if (newItem is Item item && item.Container?.GetComponent<Fabricator>() != null)
|
if (newItem == null)
|
||||||
{
|
{
|
||||||
GameAnalyticsManager.AddDesignEvent("ItemFabricated:" + (GameMain.GameSession?.GameMode?.Preset.Identifier ?? "none".ToIdentifier()) + ":" + item.Prefab.Identifier);
|
DebugConsole.ThrowError("Received an item spawn message, but spawning the item failed.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (newItem.Container?.GetComponent<Fabricator>() != null)
|
||||||
|
{
|
||||||
|
GameAnalyticsManager.AddDesignEvent("ItemFabricated:" + (GameMain.GameSession?.GameMode?.Preset.Identifier ?? "none".ToIdentifier()) + ":" + newItem.Prefab.Identifier);
|
||||||
|
}
|
||||||
|
receivedEvents.Add((newItem, false));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case (byte)SpawnableType.Character:
|
case (byte)SpawnableType.Character:
|
||||||
Character.ReadSpawnData(message);
|
var character = Character.ReadSpawnData(message);
|
||||||
|
if (character == null)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Received character spawn message, but spawning the character failed.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
receivedEvents.Add((character, false));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DebugConsole.ThrowError("Received invalid entity spawn message (unknown spawnable type)");
|
DebugConsole.ThrowError("Received invalid entity spawn message (unknown spawnable type)");
|
||||||
|
|||||||
@@ -79,13 +79,14 @@ namespace Barotrauma.Networking
|
|||||||
Starting,
|
Starting,
|
||||||
WaitingForStartGameFinalize,
|
WaitingForStartGameFinalize,
|
||||||
Started,
|
Started,
|
||||||
TimedOut,
|
|
||||||
Error,
|
Error,
|
||||||
Interrupted
|
Interrupted
|
||||||
}
|
}
|
||||||
|
|
||||||
private RoundInitStatus roundInitStatus = RoundInitStatus.NotStarted;
|
private RoundInitStatus roundInitStatus = RoundInitStatus.NotStarted;
|
||||||
|
|
||||||
|
public bool RoundStarting => roundInitStatus == RoundInitStatus.Starting || roundInitStatus == RoundInitStatus.WaitingForStartGameFinalize;
|
||||||
|
|
||||||
private byte myID;
|
private byte myID;
|
||||||
|
|
||||||
private readonly List<Client> otherClients;
|
private readonly List<Client> otherClients;
|
||||||
@@ -692,11 +693,8 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
GameMain.LuaCs.Networking.NetMessageReceived(inc, header);
|
GameMain.LuaCs.Networking.NetMessageReceived(inc, header);
|
||||||
|
|
||||||
if (roundInitStatus != RoundInitStatus.Started &&
|
if (roundInitStatus == RoundInitStatus.WaitingForStartGameFinalize &&
|
||||||
roundInitStatus != RoundInitStatus.NotStarted &&
|
roundInitStatus == RoundInitStatus.Started &&
|
||||||
roundInitStatus != RoundInitStatus.Error &&
|
|
||||||
roundInitStatus != RoundInitStatus.Interrupted &&
|
|
||||||
header != ServerPacketHeader.STARTGAMEFINALIZE &&
|
|
||||||
header != ServerPacketHeader.ENDGAME &&
|
header != ServerPacketHeader.ENDGAME &&
|
||||||
header != ServerPacketHeader.PING_REQUEST &&
|
header != ServerPacketHeader.PING_REQUEST &&
|
||||||
header != ServerPacketHeader.FILE_TRANSFER)
|
header != ServerPacketHeader.FILE_TRANSFER)
|
||||||
@@ -1688,12 +1686,15 @@ namespace Barotrauma.Networking
|
|||||||
roundInitStatus = RoundInitStatus.WaitingForStartGameFinalize;
|
roundInitStatus = RoundInitStatus.WaitingForStartGameFinalize;
|
||||||
|
|
||||||
DateTime? timeOut = null;
|
DateTime? timeOut = null;
|
||||||
|
TimeSpan timeOutDuration = new TimeSpan(0, 0, seconds: 30);
|
||||||
DateTime requestFinalizeTime = DateTime.Now;
|
DateTime requestFinalizeTime = DateTime.Now;
|
||||||
TimeSpan requestFinalizeInterval = new TimeSpan(0, 0, 2);
|
TimeSpan requestFinalizeInterval = new TimeSpan(0, 0, 2);
|
||||||
IWriteMessage msg = new WriteOnlyMessage();
|
IWriteMessage msg = new WriteOnlyMessage();
|
||||||
msg.Write((byte)ClientPacketHeader.REQUEST_STARTGAMEFINALIZE);
|
msg.Write((byte)ClientPacketHeader.REQUEST_STARTGAMEFINALIZE);
|
||||||
clientPeer.Send(msg, DeliveryMethod.Unreliable);
|
clientPeer.Send(msg, DeliveryMethod.Unreliable);
|
||||||
|
|
||||||
|
GUIMessageBox interruptPrompt = null;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -1707,11 +1708,30 @@ namespace Barotrauma.Networking
|
|||||||
clientPeer.Send(msg, DeliveryMethod.Unreliable);
|
clientPeer.Send(msg, DeliveryMethod.Unreliable);
|
||||||
requestFinalizeTime = DateTime.Now + requestFinalizeInterval;
|
requestFinalizeTime = DateTime.Now + requestFinalizeInterval;
|
||||||
}
|
}
|
||||||
if (DateTime.Now > timeOut)
|
if (DateTime.Now > timeOut && interruptPrompt == null)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Error while starting the round (did not receive STARTGAMEFINALIZE message from the server). Stopping the round...");
|
interruptPrompt = new GUIMessageBox(string.Empty, TextManager.Get("WaitingForStartGameFinalizeTakingTooLong"),
|
||||||
roundInitStatus = RoundInitStatus.TimedOut;
|
new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("No") })
|
||||||
break;
|
{
|
||||||
|
DisplayInLoadingScreens = true
|
||||||
|
};
|
||||||
|
interruptPrompt.Buttons[0].OnClicked += (btn, userData) =>
|
||||||
|
{
|
||||||
|
roundInitStatus = RoundInitStatus.Interrupted;
|
||||||
|
DebugConsole.ThrowError("Error while starting the round (did not receive STARTGAMEFINALIZE message from the server). Returning to the lobby...");
|
||||||
|
gameStarted = true;
|
||||||
|
GameMain.NetLobbyScreen.Select();
|
||||||
|
interruptPrompt.Close();
|
||||||
|
interruptPrompt = null;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
interruptPrompt.Buttons[1].OnClicked += (btn, userData) =>
|
||||||
|
{
|
||||||
|
timeOut = DateTime.Now + timeOutDuration;
|
||||||
|
interruptPrompt.Close();
|
||||||
|
interruptPrompt = null;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1723,7 +1743,7 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
|
|
||||||
//wait for up to 30 seconds for the server to send the STARTGAMEFINALIZE message
|
//wait for up to 30 seconds for the server to send the STARTGAMEFINALIZE message
|
||||||
timeOut = DateTime.Now + new TimeSpan(0, 0, seconds: 30);
|
timeOut = DateTime.Now + timeOutDuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!connected)
|
if (!connected)
|
||||||
@@ -1745,6 +1765,9 @@ namespace Barotrauma.Networking
|
|||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interruptPrompt?.Close();
|
||||||
|
interruptPrompt = null;
|
||||||
|
|
||||||
if (roundInitStatus != RoundInitStatus.Started)
|
if (roundInitStatus != RoundInitStatus.Started)
|
||||||
{
|
{
|
||||||
if (roundInitStatus != RoundInitStatus.Interrupted)
|
if (roundInitStatus != RoundInitStatus.Interrupted)
|
||||||
@@ -2713,6 +2736,8 @@ namespace Barotrauma.Networking
|
|||||||
SteamManager.LeaveLobby();
|
SteamManager.LeaveLobby();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CampaignMode.StartRoundCancellationToken?.Cancel();
|
||||||
|
|
||||||
clientPeer?.Close();
|
clientPeer?.Close();
|
||||||
clientPeer = null;
|
clientPeer = null;
|
||||||
|
|
||||||
@@ -3098,7 +3123,31 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
protected GUIFrame inGameHUD;
|
protected GUIFrame inGameHUD;
|
||||||
protected ChatBox chatBox;
|
protected ChatBox chatBox;
|
||||||
|
|
||||||
public GUIButton ShowLogButton; //TODO: move to NetLobbyScreen
|
public GUIButton ShowLogButton; //TODO: move to NetLobbyScreen
|
||||||
|
private bool hasPermissionToUseLogButton;
|
||||||
|
|
||||||
|
public void UpdateLogButtonPermissions()
|
||||||
|
{
|
||||||
|
hasPermissionToUseLogButton = GameMain.Client.HasPermission(ClientPermissions.ServerLog);
|
||||||
|
UpdateLogButtonVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateLogButtonVisibility()
|
||||||
|
{
|
||||||
|
if (ShowLogButton != null)
|
||||||
|
{
|
||||||
|
if (Screen.Selected != GameMain.GameScreen)
|
||||||
|
{
|
||||||
|
ShowLogButton.Visible = hasPermissionToUseLogButton;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var campaign = GameMain.GameSession?.Campaign;
|
||||||
|
ShowLogButton.Visible = hasPermissionToUseLogButton && (campaign == null || !campaign.ShowCampaignUI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public GUIFrame InGameHUD
|
public GUIFrame InGameHUD
|
||||||
{
|
{
|
||||||
@@ -3178,6 +3227,8 @@ namespace Barotrauma.Networking
|
|||||||
msgBox = GameMain.NetLobbyScreen.ChatInput;
|
msgBox = GameMain.NetLobbyScreen.ChatInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateLogButtonVisibility();
|
||||||
|
|
||||||
if (gameStarted && Screen.Selected == GameMain.GameScreen)
|
if (gameStarted && Screen.Selected == GameMain.GameScreen)
|
||||||
{
|
{
|
||||||
var controller = Character.Controlled?.SelectedConstruction?.GetComponent<Controller>();
|
var controller = Character.Controlled?.SelectedConstruction?.GetComponent<Controller>();
|
||||||
@@ -3653,6 +3704,19 @@ namespace Barotrauma.Networking
|
|||||||
errorLines.Add(e.ErrorLine);
|
errorLines.Add(e.ErrorLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Entity.Spawner != null)
|
||||||
|
{
|
||||||
|
errorLines.Add("");
|
||||||
|
errorLines.Add("EntitySpawner events:");
|
||||||
|
foreach ((Entity entity, bool isRemoval) in Entity.Spawner.receivedEvents)
|
||||||
|
{
|
||||||
|
errorLines.Add(
|
||||||
|
(isRemoval ? "Remove " : "Create ") +
|
||||||
|
entity.ToString() +
|
||||||
|
" (" + entity.ID + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
errorLines.Add("");
|
errorLines.Add("");
|
||||||
errorLines.Add("Last debug messages:");
|
errorLines.Add("Last debug messages:");
|
||||||
for (int i = DebugConsole.Messages.Count - 1; i > 0 && i > DebugConsole.Messages.Count - 15; i--)
|
for (int i = DebugConsole.Messages.Count - 1; i > 0 && i > DebugConsole.Messages.Count - 15; i--)
|
||||||
|
|||||||
+4
-1
@@ -153,7 +153,10 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
if (!isActive) { return; }
|
if (!isActive) { return; }
|
||||||
|
|
||||||
timeout -= deltaTime;
|
if (GameMain.Client == null || !GameMain.Client.RoundStarting)
|
||||||
|
{
|
||||||
|
timeout -= deltaTime;
|
||||||
|
}
|
||||||
heartbeatTimer -= deltaTime;
|
heartbeatTimer -= deltaTime;
|
||||||
|
|
||||||
if (initializationStep != ConnectionInitialization.Password &&
|
if (initializationStep != ConnectionInitialization.Password &&
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Campaign.Wallet.TryDeduct(CampaignMode.HullRepairCost))
|
if (Campaign.TryPurchase(null, CampaignMode.HullRepairCost))
|
||||||
{
|
{
|
||||||
GameAnalyticsManager.AddMoneySpentEvent(CampaignMode.HullRepairCost, GameAnalyticsManager.MoneySink.Service, "hullrepairs");
|
GameAnalyticsManager.AddMoneySpentEvent(CampaignMode.HullRepairCost, GameAnalyticsManager.MoneySink.Service, "hullrepairs");
|
||||||
Campaign.PurchasedHullRepairs = true;
|
Campaign.PurchasedHullRepairs = true;
|
||||||
@@ -194,7 +194,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Campaign.Wallet.TryDeduct(CampaignMode.ItemRepairCost))
|
if (Campaign.TryPurchase(null, CampaignMode.ItemRepairCost))
|
||||||
{
|
{
|
||||||
GameAnalyticsManager.AddMoneySpentEvent(CampaignMode.ItemRepairCost, GameAnalyticsManager.MoneySink.Service, "devicerepairs");
|
GameAnalyticsManager.AddMoneySpentEvent(CampaignMode.ItemRepairCost, GameAnalyticsManager.MoneySink.Service, "devicerepairs");
|
||||||
Campaign.PurchasedItemRepairs = true;
|
Campaign.PurchasedItemRepairs = true;
|
||||||
@@ -246,7 +246,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Campaign.Wallet.TryDeduct(CampaignMode.ShuttleReplaceCost))
|
if (Campaign.TryPurchase(null, CampaignMode.ShuttleReplaceCost))
|
||||||
{
|
{
|
||||||
GameAnalyticsManager.AddMoneySpentEvent(CampaignMode.ShuttleReplaceCost, GameAnalyticsManager.MoneySink.Service, "retrieveshuttle");
|
GameAnalyticsManager.AddMoneySpentEvent(CampaignMode.ShuttleReplaceCost, GameAnalyticsManager.MoneySink.Service, "retrieveshuttle");
|
||||||
Campaign.PurchasedLostShuttles = true;
|
Campaign.PurchasedLostShuttles = true;
|
||||||
@@ -736,12 +736,115 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static LocalizedString GetMoney()
|
public static LocalizedString GetMoney()
|
||||||
{
|
{
|
||||||
return TextManager.GetWithVariable("PlayerCredits", "[credits]", (GameMain.GameSession?.Campaign == null) ? "0" : string.Format(CultureInfo.InvariantCulture, "{0:N0}", GameMain.GameSession.Campaign.Wallet.Balance));
|
return TextManager.GetWithVariable("PlayerCredits", "[credits]", (GameMain.GameSession?.Campaign == null) ? "0" : string.Format(CultureInfo.InvariantCulture, "{0:N0}", GameMain.GameSession.Campaign.GetBalance()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LocalizedString GetTotalBalance()
|
||||||
|
{
|
||||||
|
return TextManager.FormatCurrency(GameMain.GameSession?.Campaign is { } campaign ? campaign.GetBalance() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LocalizedString GetBankBalance()
|
||||||
|
{
|
||||||
|
return TextManager.FormatCurrency(GameMain.GameSession?.Campaign is { } campaign ? campaign.Bank.Balance : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LocalizedString GetWalletBalance()
|
||||||
|
{
|
||||||
|
return TextManager.FormatCurrency(GameMain.GameSession?.Campaign is { } campaign ? campaign.Wallet.Balance : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateMaxMissions(Location location)
|
private void UpdateMaxMissions(Location location)
|
||||||
{
|
{
|
||||||
hasMaxMissions = Campaign.NumberOfMissionsAtLocation(location) >= Campaign.Settings.TotalMaxMissionCount;
|
hasMaxMissions = Campaign.NumberOfMissionsAtLocation(location) >= Campaign.Settings.TotalMaxMissionCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly struct PlayerBalanceElement
|
||||||
|
{
|
||||||
|
public readonly bool DisplaySeparateBalances;
|
||||||
|
public readonly GUILayoutGroup ParentComponent;
|
||||||
|
public readonly GUILayoutGroup TotalBalanceContainer;
|
||||||
|
public readonly GUILayoutGroup BankBalanceContainer;
|
||||||
|
|
||||||
|
public PlayerBalanceElement(bool displaySeparateBalances, GUILayoutGroup parentComponent, GUILayoutGroup totalBalanceContainer, GUILayoutGroup bankBalanceContainer)
|
||||||
|
{
|
||||||
|
DisplaySeparateBalances = displaySeparateBalances;
|
||||||
|
ParentComponent = parentComponent;
|
||||||
|
TotalBalanceContainer = totalBalanceContainer;
|
||||||
|
BankBalanceContainer = bankBalanceContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlayerBalanceElement(PlayerBalanceElement element, bool displaySeparateBalances)
|
||||||
|
{
|
||||||
|
DisplaySeparateBalances = displaySeparateBalances;
|
||||||
|
ParentComponent = element.ParentComponent;
|
||||||
|
TotalBalanceContainer = element.TotalBalanceContainer;
|
||||||
|
BankBalanceContainer = element.BankBalanceContainer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PlayerBalanceElement? AddBalanceElement(GUIComponent elementParent, Vector2 relativeSize)
|
||||||
|
{
|
||||||
|
var parent = new GUILayoutGroup(new RectTransform(relativeSize, elementParent.RectTransform), isHorizontal: true, childAnchor: Anchor.TopRight);
|
||||||
|
if (GameMain.IsSingleplayer)
|
||||||
|
{
|
||||||
|
AddBalance(parent, true, TextManager.Get("campaignstore.balance"), GetTotalBalance);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool displaySeparateBalances = CampaignMode.AllowedToManageWallets();
|
||||||
|
var totalBalanceContainer = AddBalance(parent, displaySeparateBalances, TextManager.Get("campaignstore.total"), GetTotalBalance);
|
||||||
|
var bankBalanceContainer = AddBalance(parent, displaySeparateBalances, TextManager.Get("crewwallet.bank"), GetBankBalance);
|
||||||
|
AddBalance(parent, true, TextManager.Get("crewwallet.wallet"), GetWalletBalance);
|
||||||
|
var playerBalanceElement = new PlayerBalanceElement(displaySeparateBalances, parent, totalBalanceContainer, bankBalanceContainer);
|
||||||
|
parent.Recalculate();
|
||||||
|
return playerBalanceElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GUILayoutGroup AddBalance(GUIComponent parent, bool visible, LocalizedString text, GUITextBlock.TextGetterHandler textGetter)
|
||||||
|
{
|
||||||
|
float balanceContainerWidth = GameMain.IsSingleplayer ? 1 : 1 / 3f;
|
||||||
|
var rt = new RectTransform(new Vector2(balanceContainerWidth, 1.0f), parent.RectTransform)
|
||||||
|
{
|
||||||
|
MaxSize = new Point(GUI.IntScale(GUI.AdjustForTextScale(120)), int.MaxValue)
|
||||||
|
};
|
||||||
|
var balanceContainer = new GUILayoutGroup(rt, childAnchor: Anchor.TopRight)
|
||||||
|
{
|
||||||
|
RelativeSpacing = 0.005f,
|
||||||
|
Visible = visible
|
||||||
|
};
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), balanceContainer.RectTransform), text,
|
||||||
|
font: GUIStyle.Font, textAlignment: Alignment.BottomRight)
|
||||||
|
{
|
||||||
|
AutoScaleVertical = true,
|
||||||
|
ForceUpperCase = ForceUpperCase.Yes
|
||||||
|
};
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), balanceContainer.RectTransform), "",
|
||||||
|
textColor: Color.White, font: GUIStyle.SubHeadingFont, textAlignment: Alignment.TopRight)
|
||||||
|
{
|
||||||
|
AutoScaleVertical = true,
|
||||||
|
TextScale = 1.1f,
|
||||||
|
TextGetter = textGetter
|
||||||
|
};
|
||||||
|
return balanceContainer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PlayerBalanceElement? UpdateBalanceElement(PlayerBalanceElement? playerBalanceElement)
|
||||||
|
{
|
||||||
|
if (playerBalanceElement is { } balanceElement)
|
||||||
|
{
|
||||||
|
bool displaySeparateBalances = CampaignMode.AllowedToManageWallets();
|
||||||
|
if (displaySeparateBalances != balanceElement.DisplaySeparateBalances)
|
||||||
|
{
|
||||||
|
balanceElement.TotalBalanceContainer.Visible = displaySeparateBalances;
|
||||||
|
balanceElement.BankBalanceContainer.Visible = displaySeparateBalances;
|
||||||
|
playerBalanceElement = new PlayerBalanceElement(balanceElement, displaySeparateBalances);
|
||||||
|
balanceElement.ParentComponent.Recalculate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return playerBalanceElement;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -966,7 +966,15 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
OnClicked = (_, __) =>
|
OnClicked = (_, __) =>
|
||||||
{
|
{
|
||||||
GameMain.Client?.RequestSelectMode(ModeList.Content.GetChildIndex(ModeList.Content.GetChildByUserData(GameModePreset.Sandbox)));
|
if (GameMain.Client == null) { return false; }
|
||||||
|
if (GameMain.Client.GameStarted)
|
||||||
|
{
|
||||||
|
GameMain.Client.RequestRoundEnd(save: false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GameMain.Client.RequestSelectMode(ModeList.Content.GetChildIndex(ModeList.Content.GetChildByUserData(GameModePreset.Sandbox)));
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1344,9 +1352,9 @@ namespace Barotrauma
|
|||||||
shuttleTickBox.Enabled = GameMain.Client.HasPermission(ClientPermissions.ManageSettings) && !GameMain.Client.GameStarted;
|
shuttleTickBox.Enabled = GameMain.Client.HasPermission(ClientPermissions.ManageSettings) && !GameMain.Client.GameStarted;
|
||||||
SubList.Enabled = !CampaignFrame.Visible && (GameMain.Client.ServerSettings.AllowSubVoting || GameMain.Client.HasPermission(ClientPermissions.SelectSub));
|
SubList.Enabled = !CampaignFrame.Visible && (GameMain.Client.ServerSettings.AllowSubVoting || GameMain.Client.HasPermission(ClientPermissions.SelectSub));
|
||||||
ShuttleList.Enabled = ShuttleList.ButtonEnabled = GameMain.Client.HasPermission(ClientPermissions.SelectSub) && !GameMain.Client.GameStarted;
|
ShuttleList.Enabled = ShuttleList.ButtonEnabled = GameMain.Client.HasPermission(ClientPermissions.SelectSub) && !GameMain.Client.GameStarted;
|
||||||
ModeList.Enabled = GameMain.Client.ServerSettings.AllowModeVoting || GameMain.Client.HasPermission(ClientPermissions.SelectMode);
|
ModeList.Enabled = !GameMain.Client.GameStarted && (GameMain.Client.ServerSettings.AllowModeVoting || GameMain.Client.HasPermission(ClientPermissions.SelectMode));
|
||||||
LogButtons.Visible = GameMain.Client.HasPermission(ClientPermissions.ServerLog);
|
LogButtons.Visible = GameMain.Client.HasPermission(ClientPermissions.ServerLog);
|
||||||
GameMain.Client.ShowLogButton.Visible = GameMain.Client.HasPermission(ClientPermissions.ServerLog);
|
GameMain.Client.UpdateLogButtonPermissions();
|
||||||
roundControlsHolder.Children.ForEach(c => c.IgnoreLayoutGroups = !c.Visible);
|
roundControlsHolder.Children.ForEach(c => c.IgnoreLayoutGroups = !c.Visible);
|
||||||
roundControlsHolder.Children.ForEach(c => c.RectTransform.RelativeSize = Vector2.One);
|
roundControlsHolder.Children.ForEach(c => c.RectTransform.RelativeSize = Vector2.One);
|
||||||
roundControlsHolder.Recalculate();
|
roundControlsHolder.Recalculate();
|
||||||
@@ -1559,7 +1567,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContainer.RectTransform), TextManager.Get("Skills"), font: GUIStyle.SubHeadingFont);
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContainer.RectTransform), TextManager.Get("Skills"), font: GUIStyle.SubHeadingFont);
|
||||||
foreach (Skill skill in characterInfo.Job.Skills)
|
foreach (Skill skill in characterInfo.Job.GetSkills())
|
||||||
{
|
{
|
||||||
Color textColor = Color.White * (0.5f + skill.Level / 200.0f);
|
Color textColor = Color.White * (0.5f + skill.Level / 200.0f);
|
||||||
var skillText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContainer.RectTransform),
|
var skillText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContainer.RectTransform),
|
||||||
@@ -2190,17 +2198,17 @@ namespace Barotrauma
|
|||||||
canKick = canBan = canPromo = false;
|
canKick = canBan = canPromo = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ContextMenuOption> options = new List<ContextMenuOption>();
|
List<ContextMenuOption> options = new List<ContextMenuOption>
|
||||||
|
|
||||||
options.Add(new ContextMenuOption("ViewSteamProfile", isEnabled: hasSteam, onSelected: delegate
|
|
||||||
{
|
{
|
||||||
Steamworks.SteamFriends.OpenWebOverlay($"https://steamcommunity.com/profiles/{client.SteamID}");
|
new ContextMenuOption("ViewSteamProfile", isEnabled: hasSteam, onSelected: delegate
|
||||||
}));
|
{
|
||||||
|
Steamworks.SteamFriends.OpenWebOverlay($"https://steamcommunity.com/profiles/{client.SteamID}");
|
||||||
options.Add(new ContextMenuOption("ModerationMenu.ManagePlayer", isEnabled: true, onSelected: delegate
|
}),
|
||||||
{
|
new ContextMenuOption("ModerationMenu.ManagePlayer", isEnabled: true, onSelected: delegate
|
||||||
GameMain.NetLobbyScreen?.SelectPlayer(client);
|
{
|
||||||
}));
|
GameMain.NetLobbyScreen?.SelectPlayer(client);
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
// Creates sub context menu options for all the ranks
|
// Creates sub context menu options for all the ranks
|
||||||
List<ContextMenuOption> rankOptions = new List<ContextMenuOption>();
|
List<ContextMenuOption> rankOptions = new List<ContextMenuOption>();
|
||||||
|
|||||||
@@ -1170,6 +1170,9 @@ namespace Barotrauma
|
|||||||
#endif
|
#endif
|
||||||
CreateEntityElement(ep, entitiesPerRow, allEntityList.Content);
|
CreateEntityElement(ep, entitiesPerRow, allEntityList.Content);
|
||||||
}
|
}
|
||||||
|
allEntityList.Content.RectTransform.SortChildren((i1, i2) =>
|
||||||
|
string.Compare(((MapEntityPrefab)i1.GUIComponent.UserData)?.Name.Value, (i2.GUIComponent.UserData as MapEntityPrefab)?.Name.Value, StringComparison.Ordinal));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateEntityElement(MapEntityPrefab ep, int entitiesPerRow, GUIComponent parent)
|
private void CreateEntityElement(MapEntityPrefab ep, int entitiesPerRow, GUIComponent parent)
|
||||||
@@ -1911,6 +1914,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
SubmarineInfo.RefreshSavedSub(savePath);
|
SubmarineInfo.RefreshSavedSub(savePath);
|
||||||
if (prevSavePath != null && prevSavePath != savePath) { SubmarineInfo.RefreshSavedSub(prevSavePath); }
|
if (prevSavePath != null && prevSavePath != savePath) { SubmarineInfo.RefreshSavedSub(prevSavePath); }
|
||||||
|
MainSub.Info.PreviewImage = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.FilePath == savePath)?.PreviewImage;
|
||||||
|
|
||||||
string downloadFolder = Path.GetFullPath(SaveUtil.SubmarineDownloadFolder);
|
string downloadFolder = Path.GetFullPath(SaveUtil.SubmarineDownloadFolder);
|
||||||
linkedSubBox.ClearChildren();
|
linkedSubBox.ClearChildren();
|
||||||
|
|||||||
+9
-2
@@ -73,11 +73,11 @@ namespace Barotrauma.Steam
|
|||||||
{
|
{
|
||||||
if (!SteamManager.IsInitialized) { return; }
|
if (!SteamManager.IsInitialized) { return; }
|
||||||
|
|
||||||
uint numSubscribedMods = Steamworks.SteamUGC.NumSubscribedItems;
|
uint numSubscribedMods = SteamManager.GetNumSubscribedItems();
|
||||||
if (numSubscribedMods == memSubscribedModCount) { return; }
|
if (numSubscribedMods == memSubscribedModCount) { return; }
|
||||||
memSubscribedModCount = numSubscribedMods;
|
memSubscribedModCount = numSubscribedMods;
|
||||||
|
|
||||||
var subscribedIds = Steamworks.SteamUGC.GetSubscribedItems().ToHashSet();
|
var subscribedIds = SteamManager.GetSubscribedItems().ToHashSet();
|
||||||
var installedIds = ContentPackageManager.WorkshopPackages.Select(p => p.SteamWorkshopId).ToHashSet();
|
var installedIds = ContentPackageManager.WorkshopPackages.Select(p => p.SteamWorkshopId).ToHashSet();
|
||||||
foreach (var id in subscribedIds.Where(id2 => !installedIds.Contains(id2)))
|
foreach (var id in subscribedIds.Where(id2 => !installedIds.Contains(id2)))
|
||||||
{
|
{
|
||||||
@@ -93,10 +93,17 @@ namespace Barotrauma.Steam
|
|||||||
if (!t.TryGetResult(out ISet<Steamworks.Ugc.Item> publishedItems)) { return; }
|
if (!t.TryGetResult(out ISet<Steamworks.Ugc.Item> publishedItems)) { return; }
|
||||||
|
|
||||||
var allRequiredInstalled = subscribedIds.Union(publishedItems.Select(it => it.Id)).ToHashSet();
|
var allRequiredInstalled = subscribedIds.Union(publishedItems.Select(it => it.Id)).ToHashSet();
|
||||||
|
bool needsRefresh = false;
|
||||||
foreach (var id in installedIds.Where(id2 => !allRequiredInstalled.Contains(id2)))
|
foreach (var id in installedIds.Where(id2 => !allRequiredInstalled.Contains(id2)))
|
||||||
{
|
{
|
||||||
Steamworks.Ugc.Item item = new Steamworks.Ugc.Item(id);
|
Steamworks.Ugc.Item item = new Steamworks.Ugc.Item(id);
|
||||||
SteamManager.Workshop.Uninstall(item);
|
SteamManager.Workshop.Uninstall(item);
|
||||||
|
needsRefresh = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsRefresh)
|
||||||
|
{
|
||||||
|
PopulateInstalledModLists();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -214,9 +214,9 @@ namespace Barotrauma
|
|||||||
//try to place commands of the same texture
|
//try to place commands of the same texture
|
||||||
//contiguously for optimal buffer generation
|
//contiguously for optimal buffer generation
|
||||||
//while maintaining the same visual result
|
//while maintaining the same visual result
|
||||||
for (int i=1;i<commandList.Count;i++)
|
for (int i = 1; i < commandList.Count; i++)
|
||||||
{
|
{
|
||||||
if (commandList[i].Texture != commandList[i-1].Texture)
|
if (commandList[i].Texture != commandList[i - 1].Texture)
|
||||||
{
|
{
|
||||||
for (int j = i - 1; j >= 0; j--)
|
for (int j = i - 1; j >= 0; j--)
|
||||||
{
|
{
|
||||||
@@ -244,6 +244,7 @@ namespace Barotrauma
|
|||||||
//requires a vertex buffer to be rendered
|
//requires a vertex buffer to be rendered
|
||||||
CrossThread.RequestExecutionOnMainThread(() =>
|
CrossThread.RequestExecutionOnMainThread(() =>
|
||||||
{
|
{
|
||||||
|
if (isDisposed) { return; }
|
||||||
if (commandList.Count == 0) { return; }
|
if (commandList.Count == 0) { return; }
|
||||||
int startIndex = 0;
|
int startIndex = 0;
|
||||||
for (int i = 1; i < commandList.Count; i++)
|
for (int i = 1; i < commandList.Count; i++)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<RootNamespace>Barotrauma</RootNamespace>
|
<RootNamespace>Barotrauma</RootNamespace>
|
||||||
<Authors>FakeFish, Undertow Games</Authors>
|
<Authors>FakeFish, Undertow Games</Authors>
|
||||||
<Product>Barotrauma</Product>
|
<Product>Barotrauma</Product>
|
||||||
<Version>0.17.12.0</Version>
|
<Version>0.17.15.0</Version>
|
||||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||||
<Platforms>AnyCPU;x64</Platforms>
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
<AssemblyName>Barotrauma</AssemblyName>
|
<AssemblyName>Barotrauma</AssemblyName>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<RootNamespace>Barotrauma</RootNamespace>
|
<RootNamespace>Barotrauma</RootNamespace>
|
||||||
<Authors>FakeFish, Undertow Games</Authors>
|
<Authors>FakeFish, Undertow Games</Authors>
|
||||||
<Product>Barotrauma</Product>
|
<Product>Barotrauma</Product>
|
||||||
<Version>0.17.12.0</Version>
|
<Version>0.17.15.0</Version>
|
||||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||||
<Platforms>AnyCPU;x64</Platforms>
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
<AssemblyName>Barotrauma</AssemblyName>
|
<AssemblyName>Barotrauma</AssemblyName>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<RootNamespace>Barotrauma</RootNamespace>
|
<RootNamespace>Barotrauma</RootNamespace>
|
||||||
<Authors>FakeFish, Undertow Games</Authors>
|
<Authors>FakeFish, Undertow Games</Authors>
|
||||||
<Product>Barotrauma</Product>
|
<Product>Barotrauma</Product>
|
||||||
<Version>0.17.12.0</Version>
|
<Version>0.17.15.0</Version>
|
||||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||||
<Platforms>AnyCPU;x64</Platforms>
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
<AssemblyName>Barotrauma</AssemblyName>
|
<AssemblyName>Barotrauma</AssemblyName>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<RootNamespace>Barotrauma</RootNamespace>
|
<RootNamespace>Barotrauma</RootNamespace>
|
||||||
<Authors>FakeFish, Undertow Games</Authors>
|
<Authors>FakeFish, Undertow Games</Authors>
|
||||||
<Product>Barotrauma Dedicated Server</Product>
|
<Product>Barotrauma Dedicated Server</Product>
|
||||||
<Version>0.17.12.0</Version>
|
<Version>0.17.15.0</Version>
|
||||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||||
<Platforms>AnyCPU;x64</Platforms>
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
<AssemblyName>DedicatedServer</AssemblyName>
|
<AssemblyName>DedicatedServer</AssemblyName>
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
@@ -6,7 +5,7 @@
|
|||||||
<RootNamespace>Barotrauma</RootNamespace>
|
<RootNamespace>Barotrauma</RootNamespace>
|
||||||
<Authors>FakeFish, Undertow Games</Authors>
|
<Authors>FakeFish, Undertow Games</Authors>
|
||||||
<Product>Barotrauma Dedicated Server</Product>
|
<Product>Barotrauma Dedicated Server</Product>
|
||||||
<Version>0.17.12.0</Version>
|
<Version>0.17.15.0</Version>
|
||||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||||
<Platforms>AnyCPU;x64</Platforms>
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
<AssemblyName>DedicatedServer</AssemblyName>
|
<AssemblyName>DedicatedServer</AssemblyName>
|
||||||
|
|||||||
@@ -63,8 +63,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
msg.Write(Job.Prefab.Identifier);
|
msg.Write(Job.Prefab.Identifier);
|
||||||
msg.Write((byte)Job.Variant);
|
msg.Write((byte)Job.Variant);
|
||||||
msg.Write((byte)Job.Skills.Count);
|
var skills = Job.GetSkills();
|
||||||
foreach (Skill skill in Job.Skills)
|
msg.Write((byte)skills.Count());
|
||||||
|
foreach (Skill skill in skills)
|
||||||
{
|
{
|
||||||
msg.Write(skill.Identifier);
|
msg.Write(skill.Identifier);
|
||||||
msg.Write(skill.Level);
|
msg.Write(skill.Level);
|
||||||
|
|||||||
@@ -434,8 +434,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
msg.Write((byte)Info.Job.Skills.Count);
|
var skills = Info.Job.GetSkills();
|
||||||
foreach (Skill skill in Info.Job.Skills)
|
msg.Write((byte)skills.Count());
|
||||||
|
foreach (Skill skill in skills)
|
||||||
{
|
{
|
||||||
msg.Write(skill.Identifier);
|
msg.Write(skill.Identifier);
|
||||||
msg.Write(skill.Level);
|
msg.Write(skill.Level);
|
||||||
|
|||||||
@@ -2470,7 +2470,7 @@ namespace Barotrauma
|
|||||||
if (isMax) { level = 100; }
|
if (isMax) { level = 100; }
|
||||||
if (skillIdentifier == "all")
|
if (skillIdentifier == "all")
|
||||||
{
|
{
|
||||||
foreach (Skill skill in character.Info.Job.Skills)
|
foreach (Skill skill in character.Info.Job.GetSkills())
|
||||||
{
|
{
|
||||||
character.Info.SetSkillLevel(skill.Identifier, level);
|
character.Info.SetSkillLevel(skill.Identifier, level);
|
||||||
}
|
}
|
||||||
@@ -2531,30 +2531,10 @@ namespace Barotrauma
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
commands.Add(new Command("spamevents", "A debug command that creates a ton of entity events.", (string[] args) =>
|
commands.Add(new Command("spamevents", "A debug command that creates a ton of entity events.", (string[] args) =>
|
||||||
{
|
{
|
||||||
/*foreach (Item item in Item.ItemList)
|
foreach (Item item in Item.ItemList)
|
||||||
{
|
{
|
||||||
foreach (ItemComponent component in item.Components)
|
item.TryCreateServerEventSpam();
|
||||||
{
|
item.CreateStatusEvent();
|
||||||
if (component is IServerSerializable)
|
|
||||||
{
|
|
||||||
GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ComponentState, item.GetComponentIndex(component) });
|
|
||||||
}
|
|
||||||
var itemContainer = item.GetComponent<ItemContainer>();
|
|
||||||
if (itemContainer != null)
|
|
||||||
{
|
|
||||||
GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.InventoryState, 0 });
|
|
||||||
}
|
|
||||||
|
|
||||||
GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.Status });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach (Character c in Character.CharacterList)
|
|
||||||
{
|
|
||||||
GameMain.Server.CreateEntityEvent(c, new object[] { NetEntityEvent.Type.Status });
|
|
||||||
}*/
|
|
||||||
foreach (Hull hull in Hull.HullList)
|
|
||||||
{
|
|
||||||
GameMain.Server.CreateEntityEvent(hull);
|
|
||||||
}
|
}
|
||||||
foreach (Structure wall in Structure.WallList)
|
foreach (Structure wall in Structure.WallList)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace Barotrauma
|
|||||||
int itemValue = sellValues[item.ItemPrefab];
|
int itemValue = sellValues[item.ItemPrefab];
|
||||||
if (store.Balance < itemValue || item.Removed) { continue; }
|
if (store.Balance < itemValue || item.Removed) { continue; }
|
||||||
store.Balance += itemValue;
|
store.Balance += itemValue;
|
||||||
campaign.GetWallet(client).TryDeduct(itemValue);
|
campaign.TryPurchase(client, itemValue);
|
||||||
storeSpecificItems.Remove(item);
|
storeSpecificItems.Remove(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+56
-9
@@ -178,6 +178,14 @@ namespace Barotrauma
|
|||||||
GameMain.Server.ConnectedClients.None(c => c.InGame && (IsOwner(c) || c.HasPermission(permissions)));
|
GameMain.Server.ConnectedClients.None(c => c.InGame && (IsOwner(c) || c.HasPermission(permissions)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool AllowedToManageWallets(Client client)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
client.HasPermission(ClientPermissions.ManageCampaign) ||
|
||||||
|
client.HasPermission(ClientPermissions.ManageMoney) ||
|
||||||
|
IsOwner(client);
|
||||||
|
}
|
||||||
|
|
||||||
public void SaveExperiencePoints(Client client)
|
public void SaveExperiencePoints(Client client)
|
||||||
{
|
{
|
||||||
ClearSavedExperiencePoints(client);
|
ClearSavedExperiencePoints(client);
|
||||||
@@ -430,7 +438,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
public bool CanPurchaseSub(SubmarineInfo info, Client client)
|
public bool CanPurchaseSub(SubmarineInfo info, Client client)
|
||||||
=> GetWallet(client).CanAfford(info.Price) && GetCampaignSubs().Contains(info);
|
=> CanAfford(info.Price, client) && GetCampaignSubs().Contains(info);
|
||||||
|
|
||||||
private readonly List<CharacterCampaignData> discardedCharacters = new List<CharacterCampaignData>();
|
private readonly List<CharacterCampaignData> discardedCharacters = new List<CharacterCampaignData>();
|
||||||
public void DiscardClientCharacterData(Client client)
|
public void DiscardClientCharacterData(Client client)
|
||||||
@@ -755,8 +763,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
switch (purchasedHullRepairs)
|
switch (purchasedHullRepairs)
|
||||||
{
|
{
|
||||||
case true when personalWallet.CanAfford(hullRepairCost):
|
case true when GetBalance(sender) >= hullRepairCost:
|
||||||
personalWallet.Deduct(hullRepairCost);
|
TryPurchase(sender, hullRepairCost);
|
||||||
PurchasedHullRepairs = true;
|
PurchasedHullRepairs = true;
|
||||||
GameAnalyticsManager.AddMoneySpentEvent(hullRepairCost, GameAnalyticsManager.MoneySink.Service, "hullrepairs");
|
GameAnalyticsManager.AddMoneySpentEvent(hullRepairCost, GameAnalyticsManager.MoneySink.Service, "hullrepairs");
|
||||||
break;
|
break;
|
||||||
@@ -771,8 +779,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
switch (purchasedItemRepairs)
|
switch (purchasedItemRepairs)
|
||||||
{
|
{
|
||||||
case true when personalWallet.CanAfford(itemRepairCost):
|
case true when GetBalance(sender) >= itemRepairCost:
|
||||||
personalWallet.Deduct(itemRepairCost);
|
TryPurchase(sender, itemRepairCost);
|
||||||
PurchasedItemRepairs = true;
|
PurchasedItemRepairs = true;
|
||||||
GameAnalyticsManager.AddMoneySpentEvent(itemRepairCost, GameAnalyticsManager.MoneySink.Service, "devicerepairs");
|
GameAnalyticsManager.AddMoneySpentEvent(itemRepairCost, GameAnalyticsManager.MoneySink.Service, "devicerepairs");
|
||||||
break;
|
break;
|
||||||
@@ -789,7 +797,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
GameMain.Server.SendDirectChatMessage(TextManager.FormatServerMessage("ReplaceShuttleDockingPortOccupied"), sender, ChatMessageType.MessageBox);
|
GameMain.Server.SendDirectChatMessage(TextManager.FormatServerMessage("ReplaceShuttleDockingPortOccupied"), sender, ChatMessageType.MessageBox);
|
||||||
}
|
}
|
||||||
else if (purchasedLostShuttles && personalWallet.TryDeduct(shuttleRetrieveCost))
|
else if (purchasedLostShuttles && TryPurchase(sender, shuttleRetrieveCost))
|
||||||
{
|
{
|
||||||
PurchasedLostShuttles = true;
|
PurchasedLostShuttles = true;
|
||||||
GameAnalyticsManager.AddMoneySpentEvent(shuttleRetrieveCost, GameAnalyticsManager.MoneySink.Service, "retrieveshuttle");
|
GameAnalyticsManager.AddMoneySpentEvent(shuttleRetrieveCost, GameAnalyticsManager.MoneySink.Service, "retrieveshuttle");
|
||||||
@@ -972,7 +980,7 @@ namespace Barotrauma
|
|||||||
switch (transfer.Sender)
|
switch (transfer.Sender)
|
||||||
{
|
{
|
||||||
case Some<ushort> { Value: var id }:
|
case Some<ushort> { Value: var id }:
|
||||||
if (id != sender.CharacterID && !AllowedToManageCampaign(sender, ClientPermissions.ManageMoney)) { return; }
|
if (id != sender.CharacterID && !AllowedToManageWallets(sender)) { return; }
|
||||||
|
|
||||||
Wallet wallet = GetWalletByID(id);
|
Wallet wallet = GetWalletByID(id);
|
||||||
if (wallet is InvalidWallet) { return; }
|
if (wallet is InvalidWallet) { return; }
|
||||||
@@ -980,7 +988,7 @@ namespace Barotrauma
|
|||||||
TransferMoney(wallet);
|
TransferMoney(wallet);
|
||||||
break;
|
break;
|
||||||
case None<ushort> _:
|
case None<ushort> _:
|
||||||
if (!AllowedToManageCampaign(sender, ClientPermissions.ManageMoney))
|
if (!AllowedToManageWallets(sender))
|
||||||
{
|
{
|
||||||
if (transfer.Receiver is Some<ushort> { Value: var receiverId } && receiverId == sender.CharacterID)
|
if (transfer.Receiver is Some<ushort> { Value: var receiverId } && receiverId == sender.CharacterID)
|
||||||
{
|
{
|
||||||
@@ -1025,7 +1033,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
NetWalletSetSalaryUpdate update = INetSerializableStruct.Read<NetWalletSetSalaryUpdate>(msg);
|
NetWalletSetSalaryUpdate update = INetSerializableStruct.Read<NetWalletSetSalaryUpdate>(msg);
|
||||||
|
|
||||||
if (!AllowedToManageCampaign(sender, ClientPermissions.ManageMoney)) { return; }
|
if (!AllowedToManageWallets(sender)) { return; }
|
||||||
|
|
||||||
Character targetCharacter = Character.CharacterList.FirstOrDefault(c => c.ID == update.Target);
|
Character targetCharacter = Character.CharacterList.FirstOrDefault(c => c.ID == update.Target);
|
||||||
targetCharacter?.Wallet.SetRewardDistribution(update.NewRewardDistribution);
|
targetCharacter?.Wallet.SetRewardDistribution(update.NewRewardDistribution);
|
||||||
@@ -1231,6 +1239,45 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool TryPurchase(Client client, int price)
|
||||||
|
{
|
||||||
|
Wallet wallet = GetWallet(client);
|
||||||
|
if (!AllowedToManageWallets(client))
|
||||||
|
{
|
||||||
|
return wallet.TryDeduct(price);
|
||||||
|
}
|
||||||
|
|
||||||
|
int balance = wallet.Balance;
|
||||||
|
|
||||||
|
if (balance >= price)
|
||||||
|
{
|
||||||
|
return wallet.TryDeduct(price);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (balance + Bank.Balance >= price)
|
||||||
|
{
|
||||||
|
int remainder = price - balance;
|
||||||
|
if (balance > 0) { wallet.Deduct(balance); }
|
||||||
|
Bank.Deduct(remainder);
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetBalance(Client client = null)
|
||||||
|
{
|
||||||
|
if (client is null) { return 0; }
|
||||||
|
|
||||||
|
Wallet wallet = GetWallet(client);
|
||||||
|
if (!AllowedToManageWallets(client))
|
||||||
|
{
|
||||||
|
return wallet.Balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wallet.Balance + Bank.Balance;
|
||||||
|
}
|
||||||
|
|
||||||
public override void Save(XElement element)
|
public override void Save(XElement element)
|
||||||
{
|
{
|
||||||
element.Add(new XAttribute("campaignid", CampaignID));
|
element.Add(new XAttribute("campaignid", CampaignID));
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
using Barotrauma.Networking;
|
|
||||||
|
|
||||||
namespace Barotrauma.Items.Components
|
|
||||||
{
|
|
||||||
partial class OutpostTerminal : ItemComponent, IClientSerializable, IServerSerializable
|
|
||||||
{
|
|
||||||
public void ServerEventRead(IReadMessage msg, Client c)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -188,11 +188,10 @@ namespace Barotrauma.Items.Components
|
|||||||
//already connected, no need to do anything
|
//already connected, no need to do anything
|
||||||
if (Connections[i].Wires.Contains(newWire)) { continue; }
|
if (Connections[i].Wires.Contains(newWire)) { continue; }
|
||||||
|
|
||||||
Connections[i].TryAddLink(newWire);
|
|
||||||
newWire.Connect(Connections[i], true, true);
|
newWire.Connect(Connections[i], true, true);
|
||||||
|
Connections[i].TryAddLink(newWire);
|
||||||
|
|
||||||
var otherConnection = newWire.OtherConnection(Connections[i]);
|
var otherConnection = newWire.OtherConnection(Connections[i]);
|
||||||
|
|
||||||
if (otherConnection == null)
|
if (otherConnection == null)
|
||||||
{
|
{
|
||||||
GameServer.Log(GameServer.CharacterLogName(c.Character) + " connected a wire to " +
|
GameServer.Log(GameServer.CharacterLogName(c.Character) + " connected a wire to " +
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ namespace Barotrauma
|
|||||||
Vector2? worldPosition = applyStatusEffectEventData.WorldPosition;
|
Vector2? worldPosition = applyStatusEffectEventData.WorldPosition;
|
||||||
|
|
||||||
Character targetCharacter = applyStatusEffectEventData.TargetCharacter;
|
Character targetCharacter = applyStatusEffectEventData.TargetCharacter;
|
||||||
|
if (targetCharacter != null && targetCharacter.Removed) { targetCharacter = null; }
|
||||||
byte targetLimbIndex = targetLimb != null && targetCharacter != null ? (byte)Array.IndexOf(targetCharacter.AnimController.Limbs, targetLimb) : (byte)255;
|
byte targetLimbIndex = targetLimb != null && targetCharacter != null ? (byte)Array.IndexOf(targetCharacter.AnimController.Limbs, targetLimb) : (byte)255;
|
||||||
|
|
||||||
msg.WriteRangedInteger((int)actionType, 0, Enum.GetValues(typeof(ActionType)).Length - 1);
|
msg.WriteRangedInteger((int)actionType, 0, Enum.GetValues(typeof(ActionType)).Length - 1);
|
||||||
@@ -372,5 +373,20 @@ namespace Barotrauma
|
|||||||
if (!ic.ValidateEventData(eventData)) { throw new Exception($"Component event creation failed: {typeof(T).Name}.{nameof(ItemComponent.ValidateEventData)} returned false"); }
|
if (!ic.ValidateEventData(eventData)) { throw new Exception($"Component event creation failed: {typeof(T).Name}.{nameof(ItemComponent.ValidateEventData)} returned false"); }
|
||||||
GameMain.Server.CreateEntityEvent(this, eventData);
|
GameMain.Server.CreateEntityEvent(this, eventData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
public void TryCreateServerEventSpam()
|
||||||
|
{
|
||||||
|
if (GameMain.Server == null) { return; }
|
||||||
|
|
||||||
|
foreach (ItemComponent ic in components)
|
||||||
|
{
|
||||||
|
if (!(ic is IServerSerializable)) { continue; }
|
||||||
|
var eventData = new ComponentStateEventData(ic, ic.ServerGetEventData());
|
||||||
|
if (!ic.ValidateEventData(eventData)) { continue; }
|
||||||
|
GameMain.Server.CreateEntityEvent(this, eventData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,10 +160,14 @@ namespace Barotrauma.Networking
|
|||||||
return Connection.EndpointMatches(endPoint);
|
return Connection.EndpointMatches(endPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetPermissions(ClientPermissions permissions, List<DebugConsole.Command> permittedConsoleCommands)
|
public void SetPermissions(ClientPermissions permissions, IEnumerable<DebugConsole.Command> permittedConsoleCommands)
|
||||||
{
|
{
|
||||||
this.Permissions = permissions;
|
this.Permissions = permissions;
|
||||||
this.PermittedConsoleCommands = new List<DebugConsole.Command>(permittedConsoleCommands);
|
this.PermittedConsoleCommands.Clear();
|
||||||
|
foreach (var command in permittedConsoleCommands)
|
||||||
|
{
|
||||||
|
this.PermittedConsoleCommands.Add(command);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GivePermission(ClientPermissions permission)
|
public void GivePermission(ClientPermissions permission)
|
||||||
|
|||||||
@@ -15,11 +15,14 @@ namespace Barotrauma
|
|||||||
if (GameMain.Server == null || spawnOrRemove?.Entity == null) { return; }
|
if (GameMain.Server == null || spawnOrRemove?.Entity == null) { return; }
|
||||||
|
|
||||||
GameMain.Server.CreateEntityEvent(this, spawnOrRemove);
|
GameMain.Server.CreateEntityEvent(this, spawnOrRemove);
|
||||||
if (spawnOrRemove.Entity is Character { Info: { } } character)
|
if (spawnOrRemove is SpawnEntity)
|
||||||
{
|
{
|
||||||
foreach (var statKey in character.Info.SavedStatValues.Keys)
|
if (spawnOrRemove.Entity is Character { Info: { } } character && !character.Removed)
|
||||||
{
|
{
|
||||||
GameMain.NetworkMember.CreateEntityEvent(character, new Character.UpdatePermanentStatsEventData(statKey));
|
foreach (var statKey in character.Info.SavedStatValues.Keys)
|
||||||
|
{
|
||||||
|
GameMain.NetworkMember.CreateEntityEvent(character, new Character.UpdatePermanentStatsEventData(statKey));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -286,7 +286,10 @@ namespace Barotrauma.Networking
|
|||||||
if (newClient.Connection == OwnerConnection && OwnerConnection != null)
|
if (newClient.Connection == OwnerConnection && OwnerConnection != null)
|
||||||
{
|
{
|
||||||
newClient.GivePermission(ClientPermissions.All);
|
newClient.GivePermission(ClientPermissions.All);
|
||||||
newClient.PermittedConsoleCommands.AddRange(DebugConsole.Commands);
|
foreach (var command in DebugConsole.Commands)
|
||||||
|
{
|
||||||
|
newClient.PermittedConsoleCommands.Add(command);
|
||||||
|
}
|
||||||
SendConsoleMessage("Granted all permissions to " + newClient.Name + ".", newClient);
|
SendConsoleMessage("Granted all permissions to " + newClient.Name + ".", newClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1239,16 +1242,6 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#warning TODO: remove this later
|
|
||||||
/*private IEnumerable<object> RoundRestartLoop()
|
|
||||||
{
|
|
||||||
yield return new WaitForSeconds(8.0f);
|
|
||||||
EndGame();
|
|
||||||
yield return new WaitForSeconds(8.0f);
|
|
||||||
StartGame();
|
|
||||||
yield return CoroutineStatus.Success;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
private void ReadCrewMessage(IReadMessage inc, Client sender)
|
private void ReadCrewMessage(IReadMessage inc, Client sender)
|
||||||
{
|
{
|
||||||
if (GameMain.GameSession?.Campaign is MultiPlayerCampaign mpCampaign)
|
if (GameMain.GameSession?.Campaign is MultiPlayerCampaign mpCampaign)
|
||||||
@@ -1407,10 +1400,16 @@ namespace Barotrauma.Networking
|
|||||||
bool continueCampaign = inc.ReadBoolean();
|
bool continueCampaign = inc.ReadBoolean();
|
||||||
if (mpCampaign != null && mpCampaign.GameOver || continueCampaign)
|
if (mpCampaign != null && mpCampaign.GameOver || continueCampaign)
|
||||||
{
|
{
|
||||||
if (mpCampaign.AllowedToManageCampaign(sender, ClientPermissions.ManageCampaign) || mpCampaign.AllowedToManageCampaign(sender, ClientPermissions.ManageMap))
|
if (gameStarted)
|
||||||
|
{
|
||||||
|
SendDirectChatMessage("Cannot continue the campaign from the previous save (round already running).", sender, ChatMessageType.Error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (mpCampaign.AllowedToManageCampaign(sender, ClientPermissions.ManageCampaign) || mpCampaign.AllowedToManageCampaign(sender, ClientPermissions.ManageMap))
|
||||||
{
|
{
|
||||||
MultiPlayerCampaign.LoadCampaign(GameMain.GameSession.SavePath);
|
MultiPlayerCampaign.LoadCampaign(GameMain.GameSession.SavePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (!gameStarted && !initiatedStartGame)
|
else if (!gameStarted && !initiatedStartGame)
|
||||||
{
|
{
|
||||||
|
|||||||
+7
@@ -364,6 +364,13 @@ namespace Barotrauma.Networking
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
netPeerConfiguration.SimulatedDuplicatesChance = GameMain.Server.SimulatedDuplicatesChance;
|
||||||
|
netPeerConfiguration.SimulatedMinimumLatency = GameMain.Server.SimulatedMinimumLatency;
|
||||||
|
netPeerConfiguration.SimulatedRandomLatency = GameMain.Server.SimulatedRandomLatency;
|
||||||
|
netPeerConfiguration.SimulatedLoss = GameMain.Server.SimulatedLoss;
|
||||||
|
#endif
|
||||||
|
|
||||||
NetOutgoingMessage lidgrenMsg = netServer.CreateMessage();
|
NetOutgoingMessage lidgrenMsg = netServer.CreateMessage();
|
||||||
byte[] msgData = new byte[msg.LengthBytes];
|
byte[] msgData = new byte[msg.LengthBytes];
|
||||||
msg.PrepareForSending(ref msgData, compressPastThreshold, out bool isCompressed, out int length);
|
msg.PrepareForSending(ref msgData, compressPastThreshold, out bool isCompressed, out int length);
|
||||||
|
|||||||
@@ -541,7 +541,7 @@ namespace Barotrauma.Networking
|
|||||||
public static void ReduceCharacterSkills(CharacterInfo characterInfo)
|
public static void ReduceCharacterSkills(CharacterInfo characterInfo)
|
||||||
{
|
{
|
||||||
if (characterInfo?.Job == null) { return; }
|
if (characterInfo?.Job == null) { return; }
|
||||||
foreach (Skill skill in characterInfo.Job.Skills)
|
foreach (Skill skill in characterInfo.Job.GetSkills())
|
||||||
{
|
{
|
||||||
var skillPrefab = characterInfo.Job.Prefab.Skills.Find(s => skill.Identifier == s.Identifier);
|
var skillPrefab = characterInfo.Job.Prefab.Skills.Find(s => skill.Identifier == s.Identifier);
|
||||||
if (skillPrefab == null) { continue; }
|
if (skillPrefab == null) { continue; }
|
||||||
|
|||||||
@@ -466,7 +466,7 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
|
|
||||||
ClientPermissions permissions = Networking.ClientPermissions.None;
|
ClientPermissions permissions = Networking.ClientPermissions.None;
|
||||||
List<DebugConsole.Command> permittedCommands = new List<DebugConsole.Command>();
|
HashSet<DebugConsole.Command> permittedCommands = new HashSet<DebugConsole.Command>();
|
||||||
|
|
||||||
if (clientElement.Attribute("preset") == null)
|
if (clientElement.Attribute("preset") == null)
|
||||||
{
|
{
|
||||||
@@ -513,7 +513,7 @@ namespace Barotrauma.Networking
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
permissions = preset.Permissions;
|
permissions = preset.Permissions;
|
||||||
permittedCommands = preset.PermittedCommands.ToList();
|
permittedCommands = preset.PermittedCommands.ToHashSet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -577,15 +577,15 @@ namespace Barotrauma.Networking
|
|||||||
foreach (string line in lines)
|
foreach (string line in lines)
|
||||||
{
|
{
|
||||||
string[] separatedLine = line.Split('|');
|
string[] separatedLine = line.Split('|');
|
||||||
if (separatedLine.Length < 3) continue;
|
if (separatedLine.Length < 3) { continue; }
|
||||||
|
|
||||||
string name = string.Join("|", separatedLine.Take(separatedLine.Length - 2));
|
string name = string.Join("|", separatedLine.Take(separatedLine.Length - 2));
|
||||||
string ip = separatedLine[separatedLine.Length - 2];
|
string ip = separatedLine[separatedLine.Length - 2];
|
||||||
|
|
||||||
ClientPermissions permissions = Networking.ClientPermissions.None;
|
ClientPermissions permissions;
|
||||||
if (Enum.TryParse(separatedLine.Last(), out permissions))
|
if (Enum.TryParse(separatedLine.Last(), out permissions))
|
||||||
{
|
{
|
||||||
ClientPermissions.Add(new SavedClientPermission(name, ip, permissions, new List<DebugConsole.Command>()));
|
ClientPermissions.Add(new SavedClientPermission(name, ip, permissions, new HashSet<DebugConsole.Command>()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<RootNamespace>Barotrauma</RootNamespace>
|
<RootNamespace>Barotrauma</RootNamespace>
|
||||||
<Authors>FakeFish, Undertow Games</Authors>
|
<Authors>FakeFish, Undertow Games</Authors>
|
||||||
<Product>Barotrauma Dedicated Server</Product>
|
<Product>Barotrauma Dedicated Server</Product>
|
||||||
<Version>0.17.12.0</Version>
|
<Version>0.17.15.0</Version>
|
||||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||||
<Platforms>AnyCPU;x64</Platforms>
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
<AssemblyName>DedicatedServer</AssemblyName>
|
<AssemblyName>DedicatedServer</AssemblyName>
|
||||||
|
|||||||
@@ -838,7 +838,7 @@ namespace Barotrauma
|
|||||||
if (container == null) { return 0; }
|
if (container == null) { return 0; }
|
||||||
if (!container.Inventory.CanBePut(containableItem)) { return 0; }
|
if (!container.Inventory.CanBePut(containableItem)) { return 0; }
|
||||||
var rootContainer = container.Item.GetRootContainer();
|
var rootContainer = container.Item.GetRootContainer();
|
||||||
if (rootContainer?.GetComponent<Fabricator>() != null || rootContainer?.GetComponent<Fabricator>() != null) { return 0; }
|
if (rootContainer?.GetComponent<Fabricator>() != null || rootContainer?.GetComponent<Deconstructor>() != null) { return 0; }
|
||||||
if (container.ShouldBeContained(containableItem, out bool isRestrictionsDefined))
|
if (container.ShouldBeContained(containableItem, out bool isRestrictionsDefined))
|
||||||
{
|
{
|
||||||
if (isRestrictionsDefined)
|
if (isRestrictionsDefined)
|
||||||
|
|||||||
@@ -57,8 +57,6 @@ namespace Barotrauma
|
|||||||
private readonly int speakerIndex;
|
private readonly int speakerIndex;
|
||||||
private readonly ImmutableHashSet<Identifier> allowedSpeakerTags;
|
private readonly ImmutableHashSet<Identifier> allowedSpeakerTags;
|
||||||
private readonly bool requireNextLine;
|
private readonly bool requireNextLine;
|
||||||
// used primarily for team1 characters interacting with escorted personnel (TODO: not used anywhere)
|
|
||||||
private readonly bool requireSight;
|
|
||||||
|
|
||||||
public NPCConversation(XElement element)
|
public NPCConversation(XElement element)
|
||||||
{
|
{
|
||||||
@@ -75,7 +73,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
Responses = element.Elements().Select(s => new NPCConversation(s)).ToImmutableArray();
|
Responses = element.Elements().Select(s => new NPCConversation(s)).ToImmutableArray();
|
||||||
requireNextLine = element.GetAttributeBool("requirenextline", false);
|
requireNextLine = element.GetAttributeBool("requirenextline", false);
|
||||||
requireSight = element.GetAttributeBool("requiresight", false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Identifier> GetCurrentFlags(Character speaker)
|
private static List<Identifier> GetCurrentFlags(Character speaker)
|
||||||
@@ -162,23 +159,38 @@ namespace Barotrauma
|
|||||||
return currentFlags;
|
return currentFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<NPCConversation> previousConversations = new List<NPCConversation>();
|
private static readonly List<NPCConversation> previousConversations = new List<NPCConversation>();
|
||||||
|
|
||||||
public static List<Pair<Character, string>> CreateRandom(List<Character> availableSpeakers)
|
public static List<(Character speaker, string line)> CreateRandom(List<Character> availableSpeakers)
|
||||||
{
|
{
|
||||||
Dictionary<int, Character> assignedSpeakers = new Dictionary<int, Character>();
|
Dictionary<int, Character> assignedSpeakers = new Dictionary<int, Character>();
|
||||||
List<Pair<Character, string>> lines = new List<Pair<Character, string>>();
|
List<(Character speaker, string line)> lines = new List<(Character speaker, string line)>();
|
||||||
|
|
||||||
|
var language = GameSettings.CurrentConfig.Language;
|
||||||
|
if (language != TextManager.DefaultLanguage && !NPCConversationCollection.Collections.ContainsKey(language))
|
||||||
|
{
|
||||||
|
DebugConsole.AddWarning($"Could not find NPC conversations for the language \"{language}\". Using \"{TextManager.DefaultLanguage}\" instead..");
|
||||||
|
language = TextManager.DefaultLanguage;
|
||||||
|
}
|
||||||
|
|
||||||
CreateConversation(availableSpeakers, assignedSpeakers, null, lines,
|
CreateConversation(availableSpeakers, assignedSpeakers, null, lines,
|
||||||
availableConversations: NPCConversationCollection.Collections[GameSettings.CurrentConfig.Language].SelectMany(cc => cc.Conversations).ToList());
|
availableConversations: NPCConversationCollection.Collections[language].SelectMany(cc => cc.Conversations).ToList());
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Pair<Character, string>> CreateRandom(List<Character> availableSpeakers, IEnumerable<Identifier> requiredFlags)
|
public static List<(Character speaker, string line)> CreateRandom(List<Character> availableSpeakers, IEnumerable<Identifier> requiredFlags)
|
||||||
{
|
{
|
||||||
Dictionary<int, Character> assignedSpeakers = new Dictionary<int, Character>();
|
Dictionary<int, Character> assignedSpeakers = new Dictionary<int, Character>();
|
||||||
List<Pair<Character, string>> lines = new List<Pair<Character, string>>();
|
List<(Character speaker, string line)> lines = new List<(Character speaker, string line)>();
|
||||||
var availableConversations = NPCConversationCollection.Collections[GameSettings.CurrentConfig.Language]
|
|
||||||
|
var language = GameSettings.CurrentConfig.Language;
|
||||||
|
if (language != TextManager.DefaultLanguage && !NPCConversationCollection.Collections.ContainsKey(language))
|
||||||
|
{
|
||||||
|
DebugConsole.AddWarning($"Could not find NPC conversations for the language \"{language}\". Using \"{TextManager.DefaultLanguage}\" instead..");
|
||||||
|
language = TextManager.DefaultLanguage;
|
||||||
|
}
|
||||||
|
|
||||||
|
var availableConversations = NPCConversationCollection.Collections[language]
|
||||||
.SelectMany(cc => cc.Conversations.Where(c => requiredFlags.All(f => c.Flags.Contains(f)))).ToList();
|
.SelectMany(cc => cc.Conversations.Where(c => requiredFlags.All(f => c.Flags.Contains(f)))).ToList();
|
||||||
if (availableConversations.Count > 0)
|
if (availableConversations.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -191,7 +203,7 @@ namespace Barotrauma
|
|||||||
List<Character> availableSpeakers,
|
List<Character> availableSpeakers,
|
||||||
Dictionary<int, Character> assignedSpeakers,
|
Dictionary<int, Character> assignedSpeakers,
|
||||||
NPCConversation baseConversation,
|
NPCConversation baseConversation,
|
||||||
IList<Pair<Character, string>> lineList,
|
IList<(Character speaker, string line)> lineList,
|
||||||
IList<NPCConversation> availableConversations,
|
IList<NPCConversation> availableConversations,
|
||||||
bool ignoreFlags = false)
|
bool ignoreFlags = false)
|
||||||
{
|
{
|
||||||
@@ -271,7 +283,7 @@ namespace Barotrauma
|
|||||||
previousConversations.Insert(0, selectedConversation);
|
previousConversations.Insert(0, selectedConversation);
|
||||||
if (previousConversations.Count > MaxPreviousConversations) previousConversations.RemoveAt(MaxPreviousConversations);
|
if (previousConversations.Count > MaxPreviousConversations) previousConversations.RemoveAt(MaxPreviousConversations);
|
||||||
}
|
}
|
||||||
lineList.Add(new Pair<Character, string>(speaker, selectedConversation.Line));
|
lineList.Add((speaker, selectedConversation.Line));
|
||||||
CreateConversation(availableSpeakers, assignedSpeakers, selectedConversation, lineList, availableConversations);
|
CreateConversation(availableSpeakers, assignedSpeakers, selectedConversation, lineList, availableConversations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2749,12 +2749,15 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (!Enabled) { return; }
|
if (!Enabled) { return; }
|
||||||
|
|
||||||
if (Level.Loaded != null && WorldPosition.Y < Level.MaxEntityDepth ||
|
if (Level.Loaded != null)
|
||||||
(Submarine != null && Submarine.WorldPosition.Y < Level.MaxEntityDepth))
|
|
||||||
{
|
{
|
||||||
Enabled = false;
|
if (WorldPosition.Y < Level.MaxEntityDepth ||
|
||||||
Kill(CauseOfDeathType.Pressure, null);
|
(Submarine != null && Submarine.WorldPosition.Y < Level.MaxEntityDepth))
|
||||||
return;
|
{
|
||||||
|
Enabled = false;
|
||||||
|
Kill(CauseOfDeathType.Pressure, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplyStatusEffects(ActionType.Always, deltaTime);
|
ApplyStatusEffects(ActionType.Always, deltaTime);
|
||||||
|
|||||||
@@ -130,15 +130,15 @@ namespace Barotrauma
|
|||||||
head = value;
|
head = value;
|
||||||
HeadSprite = null;
|
HeadSprite = null;
|
||||||
AttachmentSprites = null;
|
AttachmentSprites = null;
|
||||||
IsMale = value.Preset?.TagSet?.Contains("Male".ToIdentifier()) ?? false;
|
|
||||||
IsFemale = value.Preset?.TagSet?.Contains("Female".ToIdentifier()) ?? false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsMale { get; private set; }
|
private readonly Identifier maleIdentifier = "Male".ToIdentifier();
|
||||||
|
private readonly Identifier femaleIdentifier = "Female".ToIdentifier();
|
||||||
|
|
||||||
public bool IsFemale { get; private set; }
|
public bool IsMale { get { return head?.Preset?.TagSet?.Contains(maleIdentifier) ?? false; } }
|
||||||
|
public bool IsFemale { get { return head?.Preset?.TagSet?.Contains(femaleIdentifier) ?? false; } }
|
||||||
|
|
||||||
public CharacterInfoPrefab Prefab => CharacterPrefab.Prefabs[SpeciesName].CharacterInfoPrefab;
|
public CharacterInfoPrefab Prefab => CharacterPrefab.Prefabs[SpeciesName].CharacterInfoPrefab;
|
||||||
public class HeadPreset : ISerializableEntity
|
public class HeadPreset : ISerializableEntity
|
||||||
@@ -1033,7 +1033,7 @@ namespace Barotrauma
|
|||||||
if (Name == null || Job == null) { return 0; }
|
if (Name == null || Job == null) { return 0; }
|
||||||
|
|
||||||
int salary = 0;
|
int salary = 0;
|
||||||
foreach (Skill skill in Job.Skills)
|
foreach (Skill skill in Job.GetSkills())
|
||||||
{
|
{
|
||||||
salary += (int)(skill.Level * skill.PriceMultiplier);
|
salary += (int)(skill.Level * skill.PriceMultiplier);
|
||||||
}
|
}
|
||||||
@@ -1076,10 +1076,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (Job == null) { return; }
|
if (Job == null) { return; }
|
||||||
|
|
||||||
var skill = Job.Skills.Find(s => s.Identifier == skillIdentifier);
|
var skill = Job.GetSkill(skillIdentifier);
|
||||||
if (skill == null)
|
if (skill == null)
|
||||||
{
|
{
|
||||||
Job.Skills.Add(new Skill(skillIdentifier, level));
|
Job.IncreaseSkillLevel(skillIdentifier, level, increasePastMax: false);
|
||||||
OnSkillChanged(skillIdentifier, 0.0f, level);
|
OnSkillChanged(skillIdentifier, 0.0f, level);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
+1
-1
@@ -384,7 +384,7 @@ namespace Barotrauma
|
|||||||
foreach (var itemPrefab in ItemPrefab.Prefabs)
|
foreach (var itemPrefab in ItemPrefab.Prefabs)
|
||||||
{
|
{
|
||||||
float suitability = Math.Max(itemPrefab.GetTreatmentSuitability(Identifier), itemPrefab.GetTreatmentSuitability(AfflictionType));
|
float suitability = Math.Max(itemPrefab.GetTreatmentSuitability(Identifier), itemPrefab.GetTreatmentSuitability(AfflictionType));
|
||||||
if (suitability > 0.0f)
|
if (!MathUtils.NearlyEqual(suitability, 0.0f))
|
||||||
{
|
{
|
||||||
yield return new KeyValuePair<Identifier, float>(itemPrefab.Identifier, suitability);
|
yield return new KeyValuePair<Identifier, float>(itemPrefab.Identifier, suitability);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -154,10 +154,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void GiveItems(Character character, Submarine submarine, Rand.RandSync randSync = Rand.RandSync.Unsynced, bool createNetworkEvents = true)
|
public void GiveItems(Character character, Submarine submarine, Rand.RandSync randSync = Rand.RandSync.Unsynced, bool createNetworkEvents = true)
|
||||||
{
|
{
|
||||||
|
if (ItemSets == null || !ItemSets.Any()) { return; }
|
||||||
var spawnItems = ToolBox.SelectWeightedRandom(ItemSets.Keys.ToList(), ItemSets.Values.ToList(), randSync);
|
var spawnItems = ToolBox.SelectWeightedRandom(ItemSets.Keys.ToList(), ItemSets.Values.ToList(), randSync);
|
||||||
foreach (XElement itemElement in spawnItems.GetChildElements("item"))
|
if (spawnItems != null)
|
||||||
{
|
{
|
||||||
InitializeItem(character, itemElement, submarine, this, createNetworkEvents: createNetworkEvents);
|
foreach (XElement itemElement in spawnItems.GetChildElements("item"))
|
||||||
|
{
|
||||||
|
InitializeItem(character, itemElement, submarine, this, createNetworkEvents: createNetworkEvents);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public JobPrefab Prefab => prefab;
|
public JobPrefab Prefab => prefab;
|
||||||
|
|
||||||
public List<Skill> Skills => skills.Values.ToList();
|
|
||||||
|
|
||||||
public int Variant;
|
public int Variant;
|
||||||
|
|
||||||
public Skill PrimarySkill { get; }
|
public Skill PrimarySkill { get; }
|
||||||
@@ -82,6 +80,11 @@ namespace Barotrauma
|
|||||||
return new Job(prefab, randSync, variant);
|
return new Job(prefab, randSync, variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Skill> GetSkills()
|
||||||
|
{
|
||||||
|
return skills.Values;
|
||||||
|
}
|
||||||
|
|
||||||
public float GetSkillLevel(Identifier skillIdentifier)
|
public float GetSkillLevel(Identifier skillIdentifier)
|
||||||
{
|
{
|
||||||
if (skillIdentifier.IsEmpty) { return 0.0f; }
|
if (skillIdentifier.IsEmpty) { return 0.0f; }
|
||||||
@@ -89,6 +92,22 @@ namespace Barotrauma
|
|||||||
return skill?.Level ?? 0.0f;
|
return skill?.Level ?? 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Skill GetSkill(Identifier skillIdentifier)
|
||||||
|
{
|
||||||
|
if (skillIdentifier.IsEmpty) { return null; }
|
||||||
|
skills.TryGetValue(skillIdentifier, out Skill skill);
|
||||||
|
return skill;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OverrideSkills(Dictionary<Identifier, float> newSkills)
|
||||||
|
{
|
||||||
|
skills.Clear();
|
||||||
|
foreach (var newSkill in newSkills)
|
||||||
|
{
|
||||||
|
skills.Add(newSkill.Key, new Skill(newSkill.Key, newSkill.Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void IncreaseSkillLevel(Identifier skillIdentifier, float increase, bool increasePastMax)
|
public void IncreaseSkillLevel(Identifier skillIdentifier, float increase, bool increasePastMax)
|
||||||
{
|
{
|
||||||
if (skills.TryGetValue(skillIdentifier, out Skill skill))
|
if (skills.TryGetValue(skillIdentifier, out Skill skill))
|
||||||
@@ -171,7 +190,7 @@ namespace Barotrauma
|
|||||||
character.Inventory.TryPutItem(item, null, item.AllowedSlots);
|
character.Inventory.TryPutItem(item, null, item.AllowedSlots);
|
||||||
}
|
}
|
||||||
|
|
||||||
Wearable wearable = ((List<ItemComponent>)item.Components)?.Find(c => c is Wearable) as Wearable;
|
Wearable wearable = item.GetComponent<Wearable>();
|
||||||
if (wearable != null)
|
if (wearable != null)
|
||||||
{
|
{
|
||||||
if (Variant > 0 && Variant <= wearable.Variants)
|
if (Variant > 0 && Variant <= wearable.Variants)
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
@@ -12,7 +11,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public readonly List<string> AllowedDialogTags;
|
public readonly List<string> AllowedDialogTags;
|
||||||
|
|
||||||
private float commonness;
|
private readonly float commonness;
|
||||||
public float Commonness
|
public float Commonness
|
||||||
{
|
{
|
||||||
get { return commonness; }
|
get { return commonness; }
|
||||||
@@ -20,12 +19,22 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static IEnumerable<NPCPersonalityTrait> GetAll(LanguageIdentifier language)
|
public static IEnumerable<NPCPersonalityTrait> GetAll(LanguageIdentifier language)
|
||||||
{
|
{
|
||||||
|
if (language != TextManager.DefaultLanguage && !NPCConversationCollection.Collections.ContainsKey(language))
|
||||||
|
{
|
||||||
|
DebugConsole.AddWarning($"Could not find NPC personality traits for the language \"{language}\". Using \"{TextManager.DefaultLanguage}\" instead..");
|
||||||
|
language = TextManager.DefaultLanguage;
|
||||||
|
}
|
||||||
return NPCConversationCollection.Collections[language]
|
return NPCConversationCollection.Collections[language]
|
||||||
.SelectMany(cc => cc.PersonalityTraits.Values);
|
.SelectMany(cc => cc.PersonalityTraits.Values);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NPCPersonalityTrait Get(LanguageIdentifier language, Identifier traitName)
|
public static NPCPersonalityTrait Get(LanguageIdentifier language, Identifier traitName)
|
||||||
{
|
{
|
||||||
|
if (language != TextManager.DefaultLanguage && !NPCConversationCollection.Collections.ContainsKey(language))
|
||||||
|
{
|
||||||
|
DebugConsole.AddWarning($"Could not find NPC personality traits for the language \"{language}\". Using \"{TextManager.DefaultLanguage}\" instead..");
|
||||||
|
language = TextManager.DefaultLanguage;
|
||||||
|
}
|
||||||
return NPCConversationCollection.Collections[language]
|
return NPCConversationCollection.Collections[language]
|
||||||
.FirstOrDefault(cc => cc.PersonalityTraits.ContainsKey(traitName))
|
.FirstOrDefault(cc => cc.PersonalityTraits.ContainsKey(traitName))
|
||||||
.PersonalityTraits[traitName];
|
.PersonalityTraits[traitName];
|
||||||
|
|||||||
+4
@@ -293,6 +293,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
return Create<HumanSwimFastParams>(fullPath, speciesName, animationType);
|
return Create<HumanSwimFastParams>(fullPath, speciesName, animationType);
|
||||||
}
|
}
|
||||||
|
if (type == typeof(HumanCrouchParams))
|
||||||
|
{
|
||||||
|
return Create<HumanCrouchParams>(fullPath, speciesName, animationType);
|
||||||
|
}
|
||||||
if (type == typeof(FishWalkParams))
|
if (type == typeof(FishWalkParams))
|
||||||
{
|
{
|
||||||
return Create<FishWalkParams>(fullPath, speciesName, animationType);
|
return Create<FishWalkParams>(fullPath, speciesName, animationType);
|
||||||
|
|||||||
+1
-1
@@ -47,7 +47,7 @@ namespace Barotrauma.Abilities
|
|||||||
{
|
{
|
||||||
if (skillIdentifier == "random")
|
if (skillIdentifier == "random")
|
||||||
{
|
{
|
||||||
var skill = character.Info?.Job?.Skills?.GetRandomUnsynced();
|
var skill = character.Info?.Job?.GetSkills()?.GetRandomUnsynced();
|
||||||
if (skill == null) { return; }
|
if (skill == null) { return; }
|
||||||
character.Info?.IncreaseSkillLevel(skill.Identifier, skillIncrease, gainedFromAbility: true);
|
character.Info?.IncreaseSkillLevel(skill.Identifier, skillIncrease, gainedFromAbility: true);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -30,11 +30,12 @@ namespace Barotrauma.Abilities
|
|||||||
|
|
||||||
if (useAll && Character.Info?.Job != null)
|
if (useAll && Character.Info?.Job != null)
|
||||||
{
|
{
|
||||||
foreach (Skill skill in Character.Info.Job.Skills)
|
var skills = Character.Info.Job.GetSkills();
|
||||||
|
foreach (Skill skill in skills)
|
||||||
{
|
{
|
||||||
skillTotal += Character.GetSkillLevel(skill.Identifier);
|
skillTotal += Character.GetSkillLevel(skill.Identifier);
|
||||||
}
|
}
|
||||||
skillTotal /= Character.Info.Job.Skills.Count;
|
skillTotal /= skills.Count();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -825,7 +825,7 @@ namespace Barotrauma
|
|||||||
if (isMax) { level = 100; }
|
if (isMax) { level = 100; }
|
||||||
if (skillIdentifier == "all")
|
if (skillIdentifier == "all")
|
||||||
{
|
{
|
||||||
foreach (Skill skill in character.Info.Job.Skills)
|
foreach (Skill skill in character.Info.Job.GetSkills())
|
||||||
{
|
{
|
||||||
character.Info.SetSkillLevel(skill.Identifier, level);
|
character.Info.SetSkillLevel(skill.Identifier, level);
|
||||||
}
|
}
|
||||||
@@ -845,7 +845,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
Character.Controlled?.Info?.Job?.Skills?.Select(skill => skill.Identifier.Value).ToArray() ?? Array.Empty<string>(),
|
Character.Controlled?.Info?.Job?.GetSkills()?.Select(skill => skill.Identifier.Value).ToArray() ?? Array.Empty<string>(),
|
||||||
new[]{ "max" },
|
new[]{ "max" },
|
||||||
Character.CharacterList.Select(c => c.Name).Distinct().OrderBy(n => n).ToArray(),
|
Character.CharacterList.Select(c => c.Name).Distinct().OrderBy(n => n).ToArray(),
|
||||||
};
|
};
|
||||||
@@ -1747,20 +1747,12 @@ namespace Barotrauma
|
|||||||
ThrowError(args[1] + " is not a valid latency value.");
|
ThrowError(args[1] + " is not a valid latency value.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if CLIENT
|
if (GameMain.NetworkMember != null)
|
||||||
if (GameMain.Client != null)
|
|
||||||
{
|
{
|
||||||
GameMain.Client.SimulatedMinimumLatency = minimumLatency;
|
GameMain.NetworkMember.SimulatedMinimumLatency = minimumLatency;
|
||||||
GameMain.Client.SimulatedRandomLatency = randomLatency;
|
GameMain.NetworkMember.SimulatedRandomLatency = randomLatency;
|
||||||
}
|
}
|
||||||
#elif SERVER
|
NewMessage("Set simulated minimum latency to " + minimumLatency.ToString(CultureInfo.InvariantCulture) + " and random latency to " + randomLatency.ToString(CultureInfo.InvariantCulture) + ".", Color.White);
|
||||||
if (GameMain.Server != null)
|
|
||||||
{
|
|
||||||
GameMain.Server.SimulatedMinimumLatency = minimumLatency;
|
|
||||||
GameMain.Server.SimulatedRandomLatency = randomLatency;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
NewMessage("Set simulated minimum latency to " + minimumLatency + " and random latency to " + randomLatency + ".", Color.White);
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("simulatedloss", "simulatedloss [lossratio]: applies simulated packet loss to network messages. For example, a value of 0.1 would mean 10% of the packets are dropped. Useful for simulating real network conditions when testing the multiplayer locally.", (string[] args) =>
|
commands.Add(new Command("simulatedloss", "simulatedloss [lossratio]: applies simulated packet loss to network messages. For example, a value of 0.1 would mean 10% of the packets are dropped. Useful for simulating real network conditions when testing the multiplayer locally.", (string[] args) =>
|
||||||
@@ -1771,17 +1763,10 @@ namespace Barotrauma
|
|||||||
ThrowError(args[0] + " is not a valid loss ratio.");
|
ThrowError(args[0] + " is not a valid loss ratio.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if CLIENT
|
if (GameMain.NetworkMember != null)
|
||||||
if (GameMain.Client != null)
|
|
||||||
{
|
{
|
||||||
GameMain.Client.SimulatedLoss = loss;
|
GameMain.NetworkMember.SimulatedLoss = loss;
|
||||||
}
|
}
|
||||||
#elif SERVER
|
|
||||||
if (GameMain.Server != null)
|
|
||||||
{
|
|
||||||
GameMain.Server.SimulatedLoss = loss;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
NewMessage("Set simulated packet loss to " + (int)(loss * 100) + "%.", Color.White);
|
NewMessage("Set simulated packet loss to " + (int)(loss * 100) + "%.", Color.White);
|
||||||
}));
|
}));
|
||||||
commands.Add(new Command("simulatedduplicateschance", "simulatedduplicateschance [duplicateratio]: simulates packet duplication in network messages. For example, a value of 0.1 would mean there's a 10% chance a packet gets sent twice. Useful for simulating real network conditions when testing the multiplayer locally.", (string[] args) =>
|
commands.Add(new Command("simulatedduplicateschance", "simulatedduplicateschance [duplicateratio]: simulates packet duplication in network messages. For example, a value of 0.1 would mean there's a 10% chance a packet gets sent twice. Useful for simulating real network conditions when testing the multiplayer locally.", (string[] args) =>
|
||||||
@@ -1792,21 +1777,27 @@ namespace Barotrauma
|
|||||||
ThrowError(args[0] + " is not a valid duplicate ratio.");
|
ThrowError(args[0] + " is not a valid duplicate ratio.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if CLIENT
|
if (GameMain.NetworkMember != null)
|
||||||
if (GameMain.Client != null)
|
|
||||||
{
|
{
|
||||||
GameMain.Client.SimulatedDuplicatesChance = duplicates;
|
GameMain.NetworkMember.SimulatedDuplicatesChance = duplicates;
|
||||||
}
|
}
|
||||||
#elif SERVER
|
|
||||||
if (GameMain.Server != null)
|
|
||||||
{
|
|
||||||
GameMain.Server.SimulatedDuplicatesChance = duplicates;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
NewMessage("Set packet duplication to " + (int)(duplicates * 100) + "%.", Color.White);
|
NewMessage("Set packet duplication to " + (int)(duplicates * 100) + "%.", Color.White);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
|
||||||
|
commands.Add(new Command("simulatedlongloadingtime", "simulatedlongloadingtime [minimum loading time]: forces loading a round to take at least the specified amount of seconds.", (string[] args) =>
|
||||||
|
{
|
||||||
|
if (args.Count() < 1 || (GameMain.NetworkMember == null)) return;
|
||||||
|
if (!float.TryParse(args[0], NumberStyles.Any, CultureInfo.InvariantCulture, out float time))
|
||||||
|
{
|
||||||
|
ThrowError(args[0] + " is not a valid duration ratio.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GameSession.MinimumLoadingTime = time;
|
||||||
|
NewMessage("Set minimum loading time to " + time + " seconds.", Color.White);
|
||||||
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("storeinfo", "", (string[] args) =>
|
commands.Add(new Command("storeinfo", "", (string[] args) =>
|
||||||
{
|
{
|
||||||
if (GameMain.GameSession?.Map?.CurrentLocation is Location location)
|
if (GameMain.GameSession?.Map?.CurrentLocation is Location location)
|
||||||
|
|||||||
@@ -316,7 +316,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
// Exchange money
|
// Exchange money
|
||||||
int itemValue = item.Quantity * buyValues[item.ItemPrefab];
|
int itemValue = item.Quantity * buyValues[item.ItemPrefab];
|
||||||
campaign.GetWallet(client).TryDeduct(itemValue);
|
campaign.TryPurchase(client, itemValue);
|
||||||
GameAnalyticsManager.AddMoneySpentEvent(itemValue, GameAnalyticsManager.MoneySink.Store, item.ItemPrefab.Identifier.Value);
|
GameAnalyticsManager.AddMoneySpentEvent(itemValue, GameAnalyticsManager.MoneySink.Store, item.ItemPrefab.Identifier.Value);
|
||||||
store.Balance += itemValue;
|
store.Balance += itemValue;
|
||||||
if (removeFromCrate)
|
if (removeFromCrate)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace Barotrauma
|
|||||||
const float ConversationIntervalMax = 180.0f;
|
const float ConversationIntervalMax = 180.0f;
|
||||||
const float ConversationIntervalMultiplierMultiplayer = 5.0f;
|
const float ConversationIntervalMultiplierMultiplayer = 5.0f;
|
||||||
private float conversationTimer, conversationLineTimer;
|
private float conversationTimer, conversationLineTimer;
|
||||||
private readonly List<Pair<Character, string>> pendingConversationLines = new List<Pair<Character, string>>();
|
private readonly List<(Character speaker, string line)> pendingConversationLines = new List<(Character speaker, string line)>();
|
||||||
|
|
||||||
public const int MaxCrewSize = 16;
|
public const int MaxCrewSize = 16;
|
||||||
|
|
||||||
@@ -339,7 +339,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
#region Dialog
|
#region Dialog
|
||||||
|
|
||||||
public void AddConversation(List<Pair<Character, string>> conversationLines)
|
public void AddConversation(List<(Character speaker, string line)> conversationLines)
|
||||||
{
|
{
|
||||||
if (conversationLines == null || conversationLines.Count == 0) { return; }
|
if (conversationLines == null || conversationLines.Count == 0) { return; }
|
||||||
pendingConversationLines.AddRange(conversationLines);
|
pendingConversationLines.AddRange(conversationLines);
|
||||||
@@ -428,16 +428,16 @@ namespace Barotrauma
|
|||||||
if (conversationLineTimer <= 0.0f)
|
if (conversationLineTimer <= 0.0f)
|
||||||
{
|
{
|
||||||
//speaker of the next line can't speak, interrupt the conversation
|
//speaker of the next line can't speak, interrupt the conversation
|
||||||
if (pendingConversationLines[0].First.SpeechImpediment >= 100.0f)
|
if (pendingConversationLines[0].speaker.SpeechImpediment >= 100.0f)
|
||||||
{
|
{
|
||||||
pendingConversationLines.Clear();
|
pendingConversationLines.Clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pendingConversationLines[0].First.Speak(pendingConversationLines[0].Second, null);
|
pendingConversationLines[0].speaker.Speak(pendingConversationLines[0].line, null);
|
||||||
if (pendingConversationLines.Count > 1)
|
if (pendingConversationLines.Count > 1)
|
||||||
{
|
{
|
||||||
conversationLineTimer = MathHelper.Clamp(pendingConversationLines[0].Second.Length * 0.1f, 1.0f, 5.0f);
|
conversationLineTimer = MathHelper.Clamp(pendingConversationLines[0].line.Length * 0.1f, 1.0f, 5.0f);
|
||||||
}
|
}
|
||||||
pendingConversationLines.RemoveAt(0);
|
pendingConversationLines.RemoveAt(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -227,6 +227,21 @@ namespace Barotrauma
|
|||||||
return Bank;
|
return Bank;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual bool TryPurchase(Client client, int price)
|
||||||
|
{
|
||||||
|
return GetWallet(client).TryDeduct(price);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual int GetBalance(Client client = null)
|
||||||
|
{
|
||||||
|
return GetWallet(client).Balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanAfford(int cost, Client client = null)
|
||||||
|
{
|
||||||
|
return GetBalance(client) >= cost;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The location that's displayed as the "current one" in the map screen. Normally the current outpost or the location at the start of the level,
|
/// The location that's displayed as the "current one" in the map screen. Normally the current outpost or the location at the start of the level,
|
||||||
/// but when selecting the next destination at the end of the level at an uninhabited location we use the location at the end
|
/// but when selecting the next destination at the end of the level at an uninhabited location we use the location at the end
|
||||||
@@ -766,7 +781,7 @@ namespace Barotrauma
|
|||||||
public bool TryHireCharacter(Location location, CharacterInfo characterInfo, Client client = null)
|
public bool TryHireCharacter(Location location, CharacterInfo characterInfo, Client client = null)
|
||||||
{
|
{
|
||||||
if (characterInfo == null) { return false; }
|
if (characterInfo == null) { return false; }
|
||||||
if (!GetWallet(client).TryDeduct(characterInfo.Salary)) { return false; }
|
if (!TryPurchase(client, characterInfo.Salary)) { return false; }
|
||||||
characterInfo.IsNewHire = true;
|
characterInfo.IsNewHire = true;
|
||||||
location.RemoveHireableCharacter(characterInfo);
|
location.RemoveHireableCharacter(characterInfo);
|
||||||
CrewManager.AddCharacterInfo(characterInfo);
|
CrewManager.AddCharacterInfo(characterInfo);
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
partial class GameSession
|
partial class GameSession
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
public static float MinimumLoadingTime;
|
||||||
|
#endif
|
||||||
|
|
||||||
public enum InfoFrameTab { Crew, Mission, MyCharacter, Traitor };
|
public enum InfoFrameTab { Crew, Mission, MyCharacter, Traitor };
|
||||||
|
|
||||||
public readonly EventManager EventManager;
|
public readonly EventManager EventManager;
|
||||||
@@ -292,7 +296,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if ((GameMain.NetworkMember is null || GameMain.NetworkMember is { IsServer: true }) && cost > 0)
|
if ((GameMain.NetworkMember is null || GameMain.NetworkMember is { IsServer: true }) && cost > 0)
|
||||||
{
|
{
|
||||||
Campaign!.GetWallet(client).TryDeduct(cost);
|
Campaign!.TryPurchase(client, cost);
|
||||||
}
|
}
|
||||||
GameAnalyticsManager.AddMoneySpentEvent(cost, GameAnalyticsManager.MoneySink.SubmarineSwitch, newSubmarine.Name);
|
GameAnalyticsManager.AddMoneySpentEvent(cost, GameAnalyticsManager.MoneySink.SubmarineSwitch, newSubmarine.Name);
|
||||||
Campaign!.PendingSubmarineSwitch = newSubmarine;
|
Campaign!.PendingSubmarineSwitch = newSubmarine;
|
||||||
@@ -303,7 +307,7 @@ namespace Barotrauma
|
|||||||
public void PurchaseSubmarine(SubmarineInfo newSubmarine, Client? client = null)
|
public void PurchaseSubmarine(SubmarineInfo newSubmarine, Client? client = null)
|
||||||
{
|
{
|
||||||
if (Campaign is null) { return; }
|
if (Campaign is null) { return; }
|
||||||
if ((GameMain.NetworkMember is null || GameMain.NetworkMember is { IsServer: true }) && !Campaign.GetWallet(client).TryDeduct(newSubmarine.Price)) { return; }
|
if ((GameMain.NetworkMember is null || GameMain.NetworkMember is { IsServer: true }) && !Campaign.TryPurchase(client, newSubmarine.Price)) { return; }
|
||||||
if (!OwnedSubmarines.Any(s => s.Name == newSubmarine.Name))
|
if (!OwnedSubmarines.Any(s => s.Name == newSubmarine.Name))
|
||||||
{
|
{
|
||||||
GameAnalyticsManager.AddMoneySpentEvent(newSubmarine.Price, GameAnalyticsManager.MoneySink.SubmarinePurchase, newSubmarine.Name);
|
GameAnalyticsManager.AddMoneySpentEvent(newSubmarine.Price, GameAnalyticsManager.MoneySink.SubmarinePurchase, newSubmarine.Name);
|
||||||
@@ -355,6 +359,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void StartRound(LevelData? levelData, bool mirrorLevel = false, SubmarineInfo? startOutpost = null, SubmarineInfo? endOutpost = null)
|
public void StartRound(LevelData? levelData, bool mirrorLevel = false, SubmarineInfo? startOutpost = null, SubmarineInfo? endOutpost = null)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
DateTime startTime = DateTime.Now;
|
||||||
|
#endif
|
||||||
AfflictionPrefab.LoadAllEffects();
|
AfflictionPrefab.LoadAllEffects();
|
||||||
|
|
||||||
MirrorLevel = mirrorLevel;
|
MirrorLevel = mirrorLevel;
|
||||||
@@ -485,6 +492,15 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
double startDuration = (DateTime.Now - startTime).TotalSeconds;
|
||||||
|
if (startDuration < MinimumLoadingTime)
|
||||||
|
{
|
||||||
|
int sleepTime = (int)((MinimumLoadingTime - startDuration) * 1000);
|
||||||
|
DebugConsole.NewMessage($"Stalling round start by {sleepTime / 1000.0f} s (minimum loading time set to {MinimumLoadingTime})...", Color.Magenta);
|
||||||
|
System.Threading.Thread.Sleep(sleepTime);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
if (GameMode is CampaignMode && levelData != null) { SteamAchievementManager.OnBiomeDiscovered(levelData.Biome); }
|
if (GameMode is CampaignMode && levelData != null) { SteamAchievementManager.OnBiomeDiscovered(levelData.Biome); }
|
||||||
|
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ namespace Barotrauma
|
|||||||
if (!force)
|
if (!force)
|
||||||
{
|
{
|
||||||
if (IsOutpostInCombat()) { return HealRequestResult.Refused; }
|
if (IsOutpostInCombat()) { return HealRequestResult.Refused; }
|
||||||
if (!GetWallet(client).TryDeduct(totalCost)) { return HealRequestResult.InsufficientFunds; }
|
if (!(campaign?.TryPurchase(client, totalCost) ?? false)) { return HealRequestResult.InsufficientFunds; }
|
||||||
}
|
}
|
||||||
|
|
||||||
ImmutableArray<CharacterInfo> crew = GetCrewCharacters();
|
ImmutableArray<CharacterInfo> crew = GetCrewCharacters();
|
||||||
@@ -314,10 +314,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private int GetAdjustedPrice(int price) => campaign?.Map?.CurrentLocation is { Type: { HasOutpost: true } } currentLocation ? currentLocation.GetAdjustedHealCost(price) : int.MaxValue;
|
private int GetAdjustedPrice(int price) => campaign?.Map?.CurrentLocation is { Type: { HasOutpost: true } } currentLocation ? currentLocation.GetAdjustedHealCost(price) : int.MaxValue;
|
||||||
|
|
||||||
public Wallet GetWallet(Client? c = null)
|
public int GetBalance() => campaign?.GetBalance() ?? 0;
|
||||||
{
|
|
||||||
return campaign?.GetWallet(c) ?? Wallet.Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ImmutableArray<CharacterInfo> GetCrewCharacters()
|
public static ImmutableArray<CharacterInfo> GetCrewCharacters()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ namespace Barotrauma
|
|||||||
price = 0;
|
price = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Campaign.GetWallet(client).TryDeduct(price))
|
if (Campaign.TryPurchase(client, price))
|
||||||
{
|
{
|
||||||
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
|
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
|
||||||
{
|
{
|
||||||
@@ -313,7 +313,7 @@ namespace Barotrauma
|
|||||||
price = 0;
|
price = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Campaign.GetWallet(client).TryDeduct(price))
|
if (Campaign.TryPurchase(client, price))
|
||||||
{
|
{
|
||||||
PurchasedItemSwaps.RemoveAll(p => linkedItems.Contains(p.ItemToRemove));
|
PurchasedItemSwaps.RemoveAll(p => linkedItems.Contains(p.ItemToRemove));
|
||||||
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
|
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Microsoft.Xna.Framework;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
|
||||||
|
|
||||||
namespace Barotrauma.Items.Components
|
namespace Barotrauma.Items.Components
|
||||||
{
|
{
|
||||||
@@ -18,6 +17,8 @@ namespace Barotrauma.Items.Components
|
|||||||
const int MaxNodes = 100;
|
const int MaxNodes = 100;
|
||||||
const float MaxNodeDistance = 150.0f;
|
const float MaxNodeDistance = 150.0f;
|
||||||
|
|
||||||
|
private bool waitForVoltageRecalculation;
|
||||||
|
|
||||||
public struct Node
|
public struct Node
|
||||||
{
|
{
|
||||||
public Vector2 WorldPosition;
|
public Vector2 WorldPosition;
|
||||||
@@ -120,6 +121,7 @@ namespace Barotrauma.Items.Components
|
|||||||
CurrPowerConsumption = powerConsumption;
|
CurrPowerConsumption = powerConsumption;
|
||||||
Voltage = 0.0f;
|
Voltage = 0.0f;
|
||||||
|
|
||||||
|
waitForVoltageRecalculation = true;
|
||||||
charging = true;
|
charging = true;
|
||||||
timer = Duration;
|
timer = Duration;
|
||||||
IsActive = true;
|
IsActive = true;
|
||||||
@@ -134,6 +136,12 @@ namespace Barotrauma.Items.Components
|
|||||||
#if CLIENT
|
#if CLIENT
|
||||||
frameOffset = Rand.Int(electricitySprite.FrameCount);
|
frameOffset = Rand.Int(electricitySprite.FrameCount);
|
||||||
#endif
|
#endif
|
||||||
|
if (waitForVoltageRecalculation)
|
||||||
|
{
|
||||||
|
waitForVoltageRecalculation = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (timer <= 0.0f)
|
if (timer <= 0.0f)
|
||||||
{
|
{
|
||||||
IsActive = false;
|
IsActive = false;
|
||||||
|
|||||||
@@ -33,9 +33,6 @@ namespace Barotrauma.Items.Components
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
private JobPrefab cachedJobPrefab;
|
|
||||||
private string cachedName;
|
|
||||||
|
|
||||||
public ImmutableHashSet<Identifier> OwnerTagSet { get; set; }
|
public ImmutableHashSet<Identifier> OwnerTagSet { get; set; }
|
||||||
|
|
||||||
[Serialize("", IsPropertySaveable.Yes, alwaysUseInstanceValues: true)]
|
[Serialize("", IsPropertySaveable.Yes, alwaysUseInstanceValues: true)]
|
||||||
@@ -98,6 +95,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
OwnerName = info.Name;
|
OwnerName = info.Name;
|
||||||
OwnerJobId = info.Job?.Prefab.Identifier ?? Identifier.Empty;
|
OwnerJobId = info.Job?.Prefab.Identifier ?? Identifier.Empty;
|
||||||
|
item.AddTag($"jobid:{OwnerJobId}");
|
||||||
OwnerTagSet = info.Head.Preset.TagSet;
|
OwnerTagSet = info.Head.Preset.TagSet;
|
||||||
OwnerHairIndex = head.HairIndex;
|
OwnerHairIndex = head.HairIndex;
|
||||||
OwnerBeardIndex = head.BeardIndex;
|
OwnerBeardIndex = head.BeardIndex;
|
||||||
|
|||||||
@@ -315,6 +315,15 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Client GetUsingClient()
|
||||||
|
{
|
||||||
|
#if SERVER
|
||||||
|
return GameMain.Server.ConnectedClients.Find(c => c.Character == user);
|
||||||
|
#elif CLIENT
|
||||||
|
return null;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
private void Fabricate()
|
private void Fabricate()
|
||||||
{
|
{
|
||||||
RefreshAvailableIngredients();
|
RefreshAvailableIngredients();
|
||||||
@@ -327,9 +336,20 @@ namespace Barotrauma.Items.Components
|
|||||||
if (fabricatedItem.RequiredMoney > 0)
|
if (fabricatedItem.RequiredMoney > 0)
|
||||||
{
|
{
|
||||||
if (user == null) { return; }
|
if (user == null) { return; }
|
||||||
if (GameMain.GameSession?.GameMode is MultiPlayerCampaign)
|
if (GameMain.GameSession?.GameMode is MultiPlayerCampaign mpCampaign)
|
||||||
{
|
{
|
||||||
user.Wallet.Deduct(fabricatedItem.RequiredMoney);
|
#if CLIENT
|
||||||
|
mpCampaign.TryPurchase(null, fabricatedItem.RequiredMoney);
|
||||||
|
#elif SERVER
|
||||||
|
if (GetUsingClient() is { } client)
|
||||||
|
{
|
||||||
|
mpCampaign.TryPurchase(client, fabricatedItem.RequiredMoney);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
user.Wallet.Deduct(fabricatedItem.RequiredMoney);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else if (GameMain.GameSession?.GameMode is CampaignMode campaign)
|
else if (GameMain.GameSession?.GameMode is CampaignMode campaign)
|
||||||
{
|
{
|
||||||
@@ -530,6 +550,10 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
floatQuality += user.Info.GetSavedStatValue(StatTypes.IncreaseFabricationQuality, tag);
|
floatQuality += user.Info.GetSavedStatValue(StatTypes.IncreaseFabricationQuality, tag);
|
||||||
}
|
}
|
||||||
|
if (!fabricatedItem.TargetItem.Tags.Contains(fabricatedItem.TargetItem.Identifier))
|
||||||
|
{
|
||||||
|
floatQuality += user.Info.GetSavedStatValue(StatTypes.IncreaseFabricationQuality, fabricatedItem.TargetItem.Identifier);
|
||||||
|
}
|
||||||
quality = (int)floatQuality;
|
quality = (int)floatQuality;
|
||||||
|
|
||||||
const int MaxCraftingSkill = 100;
|
const int MaxCraftingSkill = 100;
|
||||||
@@ -548,17 +572,22 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (fabricableItem.RequiredMoney > 0)
|
if (fabricableItem.RequiredMoney > 0)
|
||||||
{
|
{
|
||||||
if (GameMain.GameSession?.GameMode is MultiPlayerCampaign)
|
switch (GameMain.GameSession?.GameMode)
|
||||||
{
|
{
|
||||||
if (character?.Wallet == null || character.Wallet.Balance < fabricableItem.RequiredMoney) { return false; }
|
case MultiPlayerCampaign mpCampaign:
|
||||||
}
|
{
|
||||||
else if (GameMain.GameSession?.GameMode is CampaignMode campaign)
|
if (!mpCampaign.CanAfford(fabricableItem.RequiredMoney, GetUsingClient())) { return false; }
|
||||||
{
|
|
||||||
if (campaign.Bank.Balance < fabricableItem.RequiredMoney) { return false; }
|
break;
|
||||||
}
|
}
|
||||||
else
|
case CampaignMode campaign:
|
||||||
{
|
{
|
||||||
return false;
|
if (campaign.Bank.Balance < fabricableItem.RequiredMoney) { return false; }
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-3
@@ -1,6 +1,4 @@
|
|||||||
using System;
|
using System.Xml.Linq;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
|
|
||||||
namespace Barotrauma.Items.Components
|
namespace Barotrauma.Items.Components
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -565,16 +565,20 @@ namespace Barotrauma.Items.Components
|
|||||||
//Iterate through all connections in the group to get their minmax power and sum them
|
//Iterate through all connections in the group to get their minmax power and sum them
|
||||||
foreach (Connection c in scrGroup.Connections)
|
foreach (Connection c in scrGroup.Connections)
|
||||||
{
|
{
|
||||||
Powered device = c.Item.GetComponent<Powered>();
|
foreach (var device in c.Item.GetComponents<Powered>())
|
||||||
scrGroup.MinMaxPower += device.MinMaxPowerOut(c, grid.Load);
|
{
|
||||||
|
scrGroup.MinMaxPower += device.MinMaxPowerOut(c, grid.Load);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Iterate through all connections to get their final power out provided the min max information
|
//Iterate through all connections to get their final power out provided the min max information
|
||||||
float addedPower = 0;
|
float addedPower = 0;
|
||||||
foreach (Connection c in scrGroup.Connections)
|
foreach (Connection c in scrGroup.Connections)
|
||||||
{
|
{
|
||||||
Powered device = c.Item.GetComponent<Powered>();
|
foreach (var device in c.Item.GetComponents<Powered>())
|
||||||
addedPower += device.GetConnectionPowerOut(c, grid.Power, scrGroup.MinMaxPower, grid.Load);
|
{
|
||||||
|
addedPower += device.GetConnectionPowerOut(c, grid.Power, scrGroup.MinMaxPower, grid.Load);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add the power to the grid
|
//Add the power to the grid
|
||||||
@@ -591,10 +595,12 @@ namespace Barotrauma.Items.Components
|
|||||||
grid.Voltage = newVoltage;
|
grid.Voltage = newVoltage;
|
||||||
|
|
||||||
//Iterate through all connections on that grid and run their gridResolved function
|
//Iterate through all connections on that grid and run their gridResolved function
|
||||||
foreach (Connection con in grid.Connections)
|
foreach (Connection c in grid.Connections)
|
||||||
{
|
{
|
||||||
Powered device = con.Item.GetComponent<Powered>();
|
foreach (var device in c.Item.GetComponents<Powered>())
|
||||||
device?.GridResolved(con);
|
{
|
||||||
|
device?.GridResolved(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -671,20 +677,17 @@ namespace Barotrauma.Items.Components
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected float GetAvailableInstantaneousBatteryPower()
|
protected float GetAvailableInstantaneousBatteryPower()
|
||||||
{
|
{
|
||||||
if (item.Connections == null) { return 0.0f; }
|
if (item.Connections == null || powerIn == null) { return 0.0f; }
|
||||||
float availablePower = 0.0f;
|
float availablePower = 0.0f;
|
||||||
foreach (Connection c in item.Connections)
|
var recipients = powerIn.Recipients;
|
||||||
|
foreach (Connection recipient in recipients)
|
||||||
{
|
{
|
||||||
var recipients = c.Recipients;
|
if (!recipient.IsPower || !recipient.IsOutput) { continue; }
|
||||||
foreach (Connection recipient in recipients)
|
var battery = recipient.Item?.GetComponent<PowerContainer>();
|
||||||
{
|
if (battery == null || battery.Item.Condition <= 0.0f) { continue; }
|
||||||
if (!recipient.IsPower || !recipient.IsOutput) { continue; }
|
float maxOutputPerFrame = battery.MaxOutPut / 60.0f;
|
||||||
var battery = recipient.Item?.GetComponent<PowerContainer>();
|
float framesPerMinute = 3600.0f;
|
||||||
if (battery == null) { continue; }
|
availablePower += Math.Min(battery.Charge * framesPerMinute, maxOutputPerFrame);
|
||||||
float maxOutputPerFrame = battery.MaxOutPut / 60.0f;
|
|
||||||
float framesPerMinute = 3600.0f;
|
|
||||||
availablePower += Math.Min(battery.Charge * framesPerMinute, maxOutputPerFrame);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return availablePower;
|
return availablePower;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -597,7 +597,7 @@ namespace Barotrauma.Items.Components
|
|||||||
else if (ic is PowerTransfer pt)
|
else if (ic is PowerTransfer pt)
|
||||||
{
|
{
|
||||||
//power transfer items (junction boxes, relays) don't deteriorate if they're no carrying any power
|
//power transfer items (junction boxes, relays) don't deteriorate if they're no carrying any power
|
||||||
if (Math.Abs(pt.CurrPowerConsumption) > 0.1f) { return true; }
|
if (pt.Voltage > 0.1f) { return true; }
|
||||||
}
|
}
|
||||||
else if (ic is PowerContainer pc)
|
else if (ic is PowerContainer pc)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -770,6 +770,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (slots[j].Contains(item)) { visualSlots[j].ShowBorderHighlight(GUIStyle.Green, 0.1f, 0.9f); }
|
if (slots[j].Contains(item)) { visualSlots[j].ShowBorderHighlight(GUIStyle.Green, 0.1f, 0.9f); }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (otherInventory.visualSlots != null)
|
||||||
|
{
|
||||||
for (int j = 0; j < otherInventory.capacity; j++)
|
for (int j = 0; j < otherInventory.capacity; j++)
|
||||||
{
|
{
|
||||||
if (otherInventory.slots[j].Contains(existingItems.FirstOrDefault())) { otherInventory.visualSlots[j].ShowBorderHighlight(GUIStyle.Green, 0.1f, 0.9f); }
|
if (otherInventory.slots[j].Contains(existingItems.FirstOrDefault())) { otherInventory.visualSlots[j].ShowBorderHighlight(GUIStyle.Green, 0.1f, 0.9f); }
|
||||||
|
|||||||
@@ -1792,7 +1792,7 @@ namespace Barotrauma
|
|||||||
if (Math.Abs(body.LinearVelocity.X) > 0.01f || Math.Abs(body.LinearVelocity.Y) > 0.01f || transformDirty)
|
if (Math.Abs(body.LinearVelocity.X) > 0.01f || Math.Abs(body.LinearVelocity.Y) > 0.01f || transformDirty)
|
||||||
{
|
{
|
||||||
UpdateTransform();
|
UpdateTransform();
|
||||||
if (CurrentHull == null && body.SimPosition.Y < ConvertUnits.ToSimUnits(Level.MaxEntityDepth))
|
if (CurrentHull == null && Level.Loaded != null && body.SimPosition.Y < ConvertUnits.ToSimUnits(Level.MaxEntityDepth))
|
||||||
{
|
{
|
||||||
Spawner?.AddItemToRemoveQueue(this);
|
Spawner?.AddItemToRemoveQueue(this);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -51,11 +51,26 @@ namespace Barotrauma.MapCreatures.Behavior
|
|||||||
private bool inflate;
|
private bool inflate;
|
||||||
private float pulseDelay = Rand.Range(0f, 3f);
|
private float pulseDelay = Rand.Range(0f, 3f);
|
||||||
|
|
||||||
public readonly BallastFloraBranch? ParentBranch;
|
private BallastFloraBranch? parentBranch;
|
||||||
|
public BallastFloraBranch? ParentBranch
|
||||||
|
{
|
||||||
|
get { return parentBranch; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != parentBranch)
|
||||||
|
{
|
||||||
|
parentBranch = value;
|
||||||
|
if (parentBranch != null)
|
||||||
|
{
|
||||||
|
BranchDepth = parentBranch.BranchDepth + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// How far from the root this branch is
|
/// How far from the root this branch is
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly int BranchDepth;
|
public int BranchDepth { get; private set; }
|
||||||
|
|
||||||
public float AccumulatedDamage;
|
public float AccumulatedDamage;
|
||||||
public float DamageVisualizationTimer;
|
public float DamageVisualizationTimer;
|
||||||
@@ -71,10 +86,6 @@ namespace Barotrauma.MapCreatures.Behavior
|
|||||||
{
|
{
|
||||||
ParentBranch = parentBranch;
|
ParentBranch = parentBranch;
|
||||||
ParentBallastFlora = parent;
|
ParentBallastFlora = parent;
|
||||||
if (parentBranch != null)
|
|
||||||
{
|
|
||||||
BranchDepth = parentBranch.BranchDepth + 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateHealth()
|
public void UpdateHealth()
|
||||||
@@ -319,6 +330,7 @@ namespace Barotrauma.MapCreatures.Behavior
|
|||||||
|
|
||||||
foreach (BallastFloraBranch branch in Branches)
|
foreach (BallastFloraBranch branch in Branches)
|
||||||
{
|
{
|
||||||
|
SetHull(branch);
|
||||||
if (branch.ClaimedItemId > -1)
|
if (branch.ClaimedItemId > -1)
|
||||||
{
|
{
|
||||||
if (Entity.FindEntityByID((ushort)branch.ClaimedItemId) is Item item)
|
if (Entity.FindEntityByID((ushort)branch.ClaimedItemId) is Item item)
|
||||||
@@ -422,6 +434,7 @@ namespace Barotrauma.MapCreatures.Behavior
|
|||||||
|
|
||||||
public void LoadSave(XElement element, IdRemap idRemap)
|
public void LoadSave(XElement element, IdRemap idRemap)
|
||||||
{
|
{
|
||||||
|
List<(BallastFloraBranch branch, int parentBranchId)> branches = new List<(BallastFloraBranch branch, int parentBranchId)>();
|
||||||
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
|
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
|
||||||
Offset = element.GetAttributeVector2("offset", Vector2.Zero);
|
Offset = element.GetAttributeVector2("offset", Vector2.Zero);
|
||||||
foreach (var subElement in element.Elements())
|
foreach (var subElement in element.Elements())
|
||||||
@@ -442,6 +455,14 @@ namespace Barotrauma.MapCreatures.Behavior
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ((BallastFloraBranch branch, int parentBranchId) in branches)
|
||||||
|
{
|
||||||
|
if (parentBranchId > -1 && parentBranchId < Branches.Count)
|
||||||
|
{
|
||||||
|
branch.ParentBranch = Branches[parentBranchId];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LoadBranch(XElement branchElement, IdRemap idRemap)
|
void LoadBranch(XElement branchElement, IdRemap idRemap)
|
||||||
{
|
{
|
||||||
Vector2 pos = branchElement.GetAttributeVector2("pos", Vector2.Zero);
|
Vector2 pos = branchElement.GetAttributeVector2("pos", Vector2.Zero);
|
||||||
@@ -456,13 +477,7 @@ namespace Barotrauma.MapCreatures.Behavior
|
|||||||
int claimedId = branchElement.GetAttributeInt("claimed", -1);
|
int claimedId = branchElement.GetAttributeInt("claimed", -1);
|
||||||
int parentBranchId = branchElement.GetAttributeInt("parentbranch", -1);
|
int parentBranchId = branchElement.GetAttributeInt("parentbranch", -1);
|
||||||
|
|
||||||
BallastFloraBranch? parentBranch = null;
|
BallastFloraBranch newBranch = new BallastFloraBranch(this, null, pos, VineTileType.CrossJunction, FoliageConfig.Deserialize(flowerConfig), FoliageConfig.Deserialize(leafconfig))
|
||||||
if (parentBranchId > -1)
|
|
||||||
{
|
|
||||||
parentBranch = Branches[parentBranchId];
|
|
||||||
}
|
|
||||||
|
|
||||||
BallastFloraBranch newBranch = new BallastFloraBranch(this, parentBranch, pos, VineTileType.CrossJunction, FoliageConfig.Deserialize(flowerConfig), FoliageConfig.Deserialize(leafconfig))
|
|
||||||
{
|
{
|
||||||
ID = id,
|
ID = id,
|
||||||
Health = health,
|
Health = health,
|
||||||
@@ -471,6 +486,8 @@ namespace Barotrauma.MapCreatures.Behavior
|
|||||||
BlockedSides = (TileSide) blockedSides,
|
BlockedSides = (TileSide) blockedSides,
|
||||||
IsRoot = isRoot
|
IsRoot = isRoot
|
||||||
};
|
};
|
||||||
|
branches.Add((newBranch, parentBranchId));
|
||||||
|
|
||||||
if (newBranch.IsRoot) { root = newBranch; }
|
if (newBranch.IsRoot) { root = newBranch; }
|
||||||
|
|
||||||
if (claimedId > -1)
|
if (claimedId > -1)
|
||||||
@@ -731,7 +748,7 @@ namespace Barotrauma.MapCreatures.Behavior
|
|||||||
}
|
}
|
||||||
|
|
||||||
// could probably be moved to the branch constructor
|
// could probably be moved to the branch constructor
|
||||||
private void SetHull(BallastFloraBranch branch)
|
public void SetHull(BallastFloraBranch branch)
|
||||||
{
|
{
|
||||||
branch.CurrentHull = Hull.FindHull(GetWorldPosition() + branch.Position, Parent, true);
|
branch.CurrentHull = Hull.FindHull(GetWorldPosition() + branch.Position, Parent, true);
|
||||||
}
|
}
|
||||||
@@ -1204,7 +1221,7 @@ namespace Barotrauma.MapCreatures.Behavior
|
|||||||
|
|
||||||
_entityList.Remove(this);
|
_entityList.Remove(this);
|
||||||
#if SERVER
|
#if SERVER
|
||||||
CreateNetworkMessage(new KillEventData());
|
CreateNetworkMessage(new RemoveEventData());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,11 @@ namespace Barotrauma.MapCreatures.Behavior
|
|||||||
public NetworkHeader NetworkHeader => NetworkHeader.Kill;
|
public NetworkHeader NetworkHeader => NetworkHeader.Kill;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly struct RemoveEventData : IEventData
|
||||||
|
{
|
||||||
|
public NetworkHeader NetworkHeader => NetworkHeader.Remove;
|
||||||
|
}
|
||||||
|
|
||||||
private readonly struct BranchCreateEventData : IEventData
|
private readonly struct BranchCreateEventData : IEventData
|
||||||
{
|
{
|
||||||
public NetworkHeader NetworkHeader => NetworkHeader.BranchCreate;
|
public NetworkHeader NetworkHeader => NetworkHeader.BranchCreate;
|
||||||
|
|||||||
@@ -8,10 +8,7 @@ using Microsoft.Xna.Framework;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
|
||||||
using Barotrauma.IO;
|
|
||||||
using Voronoi2;
|
using Voronoi2;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
@@ -25,7 +22,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
//all entities are disabled after they reach this depth
|
//all entities are disabled after they reach this depth
|
||||||
public const int MaxEntityDepth = -300000;
|
public const int MaxEntityDepth = -1000000;
|
||||||
public const float ShaftHeight = 1000.0f;
|
public const float ShaftHeight = 1000.0f;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The level generator won't try to adjust the width of the main path above this limit.
|
/// The level generator won't try to adjust the width of the main path above this limit.
|
||||||
|
|||||||
@@ -164,18 +164,14 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
public bool HasSpawned; //has the client spawned as a character during the current round
|
public bool HasSpawned; //has the client spawned as a character during the current round
|
||||||
|
|
||||||
private List<Client> kickVoters;
|
private readonly List<Client> kickVoters;
|
||||||
|
|
||||||
public HashSet<Identifier> GivenAchievements = new HashSet<Identifier>();
|
public HashSet<Identifier> GivenAchievements = new HashSet<Identifier>();
|
||||||
|
|
||||||
public ClientPermissions Permissions = ClientPermissions.None;
|
public ClientPermissions Permissions = ClientPermissions.None;
|
||||||
public List<DebugConsole.Command> PermittedConsoleCommands
|
public readonly HashSet<DebugConsole.Command> PermittedConsoleCommands = new HashSet<DebugConsole.Command>();
|
||||||
{
|
|
||||||
get;
|
|
||||||
private set;
|
|
||||||
}
|
|
||||||
|
|
||||||
private object[] votes;
|
private readonly object[] votes;
|
||||||
|
|
||||||
public int KickVoteCount
|
public int KickVoteCount
|
||||||
{
|
{
|
||||||
@@ -195,7 +191,6 @@ namespace Barotrauma.Networking
|
|||||||
this.Name = name;
|
this.Name = name;
|
||||||
this.ID = ID;
|
this.ID = ID;
|
||||||
|
|
||||||
PermittedConsoleCommands = new List<DebugConsole.Command>();
|
|
||||||
kickVoters = new List<Client>();
|
kickVoters = new List<Client>();
|
||||||
|
|
||||||
votes = new object[Enum.GetNames(typeof(VoteType)).Length];
|
votes = new object[Enum.GetNames(typeof(VoteType)).Length];
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace Barotrauma.Networking
|
|||||||
public readonly LocalizedString Name;
|
public readonly LocalizedString Name;
|
||||||
public readonly LocalizedString Description;
|
public readonly LocalizedString Description;
|
||||||
public readonly ClientPermissions Permissions;
|
public readonly ClientPermissions Permissions;
|
||||||
public readonly List<DebugConsole.Command> PermittedCommands;
|
public readonly HashSet<DebugConsole.Command> PermittedCommands;
|
||||||
|
|
||||||
public PermissionPreset(XElement element)
|
public PermissionPreset(XElement element)
|
||||||
{
|
{
|
||||||
@@ -51,7 +51,7 @@ namespace Barotrauma.Networking
|
|||||||
DebugConsole.ThrowError("Error in permission preset \"" + Name + "\" - " + permissionsStr + " is not a valid permission!");
|
DebugConsole.ThrowError("Error in permission preset \"" + Name + "\" - " + permissionsStr + " is not a valid permission!");
|
||||||
}
|
}
|
||||||
|
|
||||||
PermittedCommands = new List<DebugConsole.Command>();
|
PermittedCommands = new HashSet<DebugConsole.Command>();
|
||||||
if (Permissions.HasFlag(ClientPermissions.ConsoleCommands))
|
if (Permissions.HasFlag(ClientPermissions.ConsoleCommands))
|
||||||
{
|
{
|
||||||
foreach (var subElement in element.Elements())
|
foreach (var subElement in element.Elements())
|
||||||
@@ -87,7 +87,7 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool MatchesPermissions(ClientPermissions permissions, List<DebugConsole.Command> permittedConsoleCommands)
|
public bool MatchesPermissions(ClientPermissions permissions, HashSet<DebugConsole.Command> permittedConsoleCommands)
|
||||||
{
|
{
|
||||||
return permissions == this.Permissions && PermittedCommands.SequenceEqual(permittedConsoleCommands);
|
return permissions == this.Permissions && PermittedCommands.SequenceEqual(permittedConsoleCommands);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -443,6 +443,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
removeQueue.Clear();
|
removeQueue.Clear();
|
||||||
spawnQueue.Clear();
|
spawnQueue.Clear();
|
||||||
|
#if CLIENT
|
||||||
|
receivedEvents.Clear();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,18 +72,18 @@ namespace Barotrauma.Networking
|
|||||||
public readonly string EndPoint;
|
public readonly string EndPoint;
|
||||||
public readonly ulong SteamID;
|
public readonly ulong SteamID;
|
||||||
public readonly string Name;
|
public readonly string Name;
|
||||||
public List<DebugConsole.Command> PermittedCommands;
|
public HashSet<DebugConsole.Command> PermittedCommands;
|
||||||
|
|
||||||
public ClientPermissions Permissions;
|
public ClientPermissions Permissions;
|
||||||
|
|
||||||
public SavedClientPermission(string name, string endpoint, ClientPermissions permissions, List<DebugConsole.Command> permittedCommands)
|
public SavedClientPermission(string name, string endpoint, ClientPermissions permissions, HashSet<DebugConsole.Command> permittedCommands)
|
||||||
{
|
{
|
||||||
this.Name = name;
|
this.Name = name;
|
||||||
this.EndPoint = endpoint;
|
this.EndPoint = endpoint;
|
||||||
this.Permissions = permissions;
|
this.Permissions = permissions;
|
||||||
this.PermittedCommands = permittedCommands;
|
this.PermittedCommands = permittedCommands;
|
||||||
}
|
}
|
||||||
public SavedClientPermission(string name, ulong steamID, ClientPermissions permissions, List<DebugConsole.Command> permittedCommands)
|
public SavedClientPermission(string name, ulong steamID, ClientPermissions permissions, HashSet<DebugConsole.Command> permittedCommands)
|
||||||
{
|
{
|
||||||
this.Name = name;
|
this.Name = name;
|
||||||
this.SteamID = steamID;
|
this.SteamID = steamID;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Config config = new Config
|
Config config = new Config
|
||||||
{
|
{
|
||||||
Language = LanguageIdentifier.None,
|
Language = TextManager.DefaultLanguage,
|
||||||
SubEditorUndoBuffer = 32,
|
SubEditorUndoBuffer = 32,
|
||||||
MaxAutoSaves = 8,
|
MaxAutoSaves = 8,
|
||||||
AutoSaveIntervalSeconds = 300,
|
AutoSaveIntervalSeconds = 300,
|
||||||
@@ -99,6 +99,10 @@ namespace Barotrauma
|
|||||||
Config retVal = fallback ?? GetDefault();
|
Config retVal = fallback ?? GetDefault();
|
||||||
|
|
||||||
retVal.DeserializeElement(element);
|
retVal.DeserializeElement(element);
|
||||||
|
if (retVal.Language == LanguageIdentifier.None)
|
||||||
|
{
|
||||||
|
retVal.Language = TextManager.DefaultLanguage;
|
||||||
|
}
|
||||||
|
|
||||||
retVal.Graphics = GraphicsSettings.FromElements(element.GetChildElements("graphicsmode", "graphicssettings"), retVal.Graphics);
|
retVal.Graphics = GraphicsSettings.FromElements(element.GetChildElements("graphicsmode", "graphicssettings"), retVal.Graphics);
|
||||||
retVal.Audio = AudioSettings.FromElements(element.GetChildElements("audio"), retVal.Audio);
|
retVal.Audio = AudioSettings.FromElements(element.GetChildElements("audio"), retVal.Audio);
|
||||||
|
|||||||
@@ -1485,7 +1485,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
Identifier GetRandomSkill()
|
Identifier GetRandomSkill()
|
||||||
{
|
{
|
||||||
return targetCharacter.Info?.Job?.Skills.Select(s => s.Identifier).GetRandomUnsynced() ?? Identifier.Empty;
|
return targetCharacter.Info?.Job?.GetSkills().GetRandomUnsynced()?.Identifier ?? Identifier.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Steamworks.Data;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -74,6 +75,24 @@ namespace Barotrauma.Steam
|
|||||||
return Steamworks.SteamClient.Name;
|
return Steamworks.SteamClient.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static uint GetNumSubscribedItems()
|
||||||
|
{
|
||||||
|
if (!IsInitialized || !Steamworks.SteamClient.IsValid)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return Steamworks.SteamUGC.NumSubscribedItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PublishedFileId[] GetSubscribedItems()
|
||||||
|
{
|
||||||
|
if (!IsInitialized || !Steamworks.SteamClient.IsValid)
|
||||||
|
{
|
||||||
|
return new PublishedFileId[0];
|
||||||
|
}
|
||||||
|
return Steamworks.SteamUGC.GetSubscribedItems();
|
||||||
|
}
|
||||||
|
|
||||||
public static bool UnlockAchievement(string achievementIdentifier) =>
|
public static bool UnlockAchievement(string achievementIdentifier) =>
|
||||||
UnlockAchievement(achievementIdentifier.ToIdentifier());
|
UnlockAchievement(achievementIdentifier.ToIdentifier());
|
||||||
|
|
||||||
|
|||||||
@@ -250,12 +250,15 @@ namespace Barotrauma.Steam
|
|||||||
|
|
||||||
public static void DeleteFailedCopies()
|
public static void DeleteFailedCopies()
|
||||||
{
|
{
|
||||||
foreach (var dir in Directory.EnumerateDirectories(ContentPackage.WorkshopModsDir, "**"))
|
if (Directory.Exists(ContentPackage.WorkshopModsDir))
|
||||||
{
|
{
|
||||||
string copyingIndicatorPath = Path.Combine(dir, ContentPackageManager.CopyIndicatorFileName);
|
foreach (var dir in Directory.EnumerateDirectories(ContentPackage.WorkshopModsDir, "**"))
|
||||||
if (File.Exists(copyingIndicatorPath))
|
|
||||||
{
|
{
|
||||||
Directory.Delete(dir, recursive: true);
|
string copyingIndicatorPath = Path.Combine(dir, ContentPackageManager.CopyIndicatorFileName);
|
||||||
|
if (File.Exists(copyingIndicatorPath))
|
||||||
|
{
|
||||||
|
Directory.Delete(dir, recursive: true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ namespace Barotrauma
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (!lStr.IsNullOrEmpty() && lStr.Contains("‖"))
|
if (!lStr.IsNullOrEmpty() && lStr.Contains("‖"))
|
||||||
{
|
{
|
||||||
if (Debugger.IsAttached) { Debugger.Break(); }
|
//if (Debugger.IsAttached) { Debugger.Break(); }
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return Plain(lStr ?? string.Empty);
|
return Plain(lStr ?? string.Empty);
|
||||||
|
|||||||
@@ -1,3 +1,70 @@
|
|||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
v0.17.15.0
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
- Fixed crashing if a custom language doesn't configure NPC personality traits or conversations.
|
||||||
|
- Fixed crashing when you try to disguise as someone else when using a mod that overrides the vanilla human config.
|
||||||
|
- Fixed characters getting instakilled if you dive too deep in the sub editor test mode.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
v0.17.14.0
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Display both wallet and bank balance on campaign interfaces when the player has access to the bank funds.
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
- Hopefully fixed the frequent "SteamP2P connection timed out" errors during loading screens.
|
||||||
|
- Fixed "missing entity" error when a character who's stats have been modified by a talent gets removed (e.g. eaten by a monster, despawning).
|
||||||
|
- If starting a multiplayer round takes a long time, instead of throwing the "did not receive STARTGAMEFINALIZE message" error, you're asked whether you want to keep waiting or return to the lobby.
|
||||||
|
- Fixed "failed to parse the string 'COLOR.GUI.GREEN' to Color" errors when using the submarine upgrade interface in Spanish.
|
||||||
|
- Fixed junction boxes not deteriorating over time.
|
||||||
|
- Fixed turrets being able to fire without consuming power when the power is wired to some other connection than power_in.
|
||||||
|
- Fixed broken supercapacitors providing unlimited power to turrets.
|
||||||
|
- Fixed IsMale/IsFemale properties resetting when saving and reloading (not used by the vanilla game).
|
||||||
|
- Fixed haloperidol not healing psychosis.
|
||||||
|
- Fixed ballast flora sometimes becoming unkillable client-side when entering a new level.
|
||||||
|
- Fixed the Server Log button overlapping campaign interfaces by hiding it whenever a campaign interface is open.
|
||||||
|
- Fixed an inconsistency in the assault rifle mag recipe.
|
||||||
|
- Fixed job not showing up in ID card description.
|
||||||
|
- Fixed store interface not being updated when the player balance changes.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
v0.17.13.0
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Players who are allowed to manage money in the multiplayer campaign can use money directly from the bank without having to transfer it to their wallet first.
|
||||||
|
- Managing money always requires permissions: unlike other campaign-related permissions, not having anyone with permissions on the server doesn't give everyone permissions.
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
- Fixed deconstructors, fabricators and research stations not being powered in some colony modules.
|
||||||
|
- Fixed power connections not getting recalculated server-side when disconnecting and reconnecting a wire.
|
||||||
|
- Fixed client context menu not working in the tab menu if the client's not controlling a character.
|
||||||
|
- Fixed preview image disappearing when saving a sub.
|
||||||
|
- Fixed custom jobid tags not working on ID cards.
|
||||||
|
- Fixed crashing with the error "Coroutine Barotrauma.SinglePlayerCampaign+<DoLoadInitialLevel>d__16 threw an exception" when trying to give items to a human prefab instance that has no item sets configured.
|
||||||
|
- Fixed installed mods list not refreshing when uninstalling an unsubscribed mod.
|
||||||
|
- Fixed outpost reactors using mechanical skill for repairs instead of electrical.
|
||||||
|
- Fixed outdated Dugong preview image.
|
||||||
|
- Fixed Deadeye Carbine firing an inconsistent number of rounds per burst in multiplayer.
|
||||||
|
- Fixed crashing when launching the server with a fresh config file due to the language being set to None.
|
||||||
|
- Fixed crashing on startup if the workshop mod directory doesn't exist.
|
||||||
|
- Fixed "Canned Heat" not having an effect on oxygenite tanks.
|
||||||
|
- Fixed entity list's search results being in a random order in the sub editor.
|
||||||
|
- Fixed crashing when trying to view an item assembly that contains entities that can't be found in the sub editor.
|
||||||
|
- Fixed bots not taking medical items' negative effects into account when determining which meds to use, often leading to overdoses/suffocation when using opiates.
|
||||||
|
- Fixed bots trying to clean up items into deconstructors.
|
||||||
|
- Fixed clients failing to spawn items with console commands when there's a structure prefab with the same identifier (e.g. ladders).
|
||||||
|
- Fixed characters being unable to gain skills added by a mod if the job doesn't initially have those skills defined.
|
||||||
|
- Automatically correct linked submarine paths in the submarine editor.
|
||||||
|
- Fixed electrical discharge coils sometimes working with insufficient power.
|
||||||
|
- Fixed crashing when creating a humanoid character in character editor.
|
||||||
|
- Fixed cargo missions putting cargo in non-interactable and hidden-in-game containers.
|
||||||
|
- Fixed only the first Powered component being considered when determining how much power an item is supplying to the grid. Prevented alien generators from working.
|
||||||
|
- Fixed textbox's text position breaking when there's overflow and you're editing in the middle of the string.
|
||||||
|
|
||||||
---------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------
|
||||||
v0.17.12.0
|
v0.17.12.0
|
||||||
---------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user