Unstable 0.17.2.0

This commit is contained in:
Markus Isberg
2022-03-18 04:20:02 +09:00
parent 6d410cc1b7
commit cefac171f5
33 changed files with 214 additions and 135 deletions
@@ -842,7 +842,7 @@ namespace Barotrauma
ContentXElement headElement = info.Ragdoll.MainElement.Elements().FirstOrDefault(e => ContentXElement headElement = info.Ragdoll.MainElement.Elements().FirstOrDefault(e =>
e.GetAttributeString("type", "").Equals("head", StringComparison.OrdinalIgnoreCase)); e.GetAttributeString("type", "").Equals("head", StringComparison.OrdinalIgnoreCase));
ContentXElement headSpriteElement = headElement.GetChildElement("sprite"); ContentXElement headSpriteElement = headElement.GetChildElement("sprite");
string spritePathWithTags = headSpriteElement.Attribute("texture").Value; ContentPath spritePathWithTags = headSpriteElement.GetAttributeContentPath("texture");
var characterConfigElement = info.CharacterConfigElement; var characterConfigElement = info.CharacterConfigElement;
@@ -853,7 +853,7 @@ namespace Barotrauma
itemsInRow = 0; itemsInRow = 0;
foreach (var head in heads.Where(h => h.TagSet.Contains(selectedCategory))) foreach (var head in heads.Where(h => h.TagSet.Contains(selectedCategory)))
{ {
string spritePath = info.Prefab.ReplaceVars(spritePathWithTags, head); string spritePath = info.Prefab.ReplaceVars(spritePathWithTags.Value, head);
if (!File.Exists(spritePath)) { continue; } if (!File.Exists(spritePath)) { continue; }
@@ -521,7 +521,7 @@ namespace Barotrauma
new GUITextBlock(new RectTransform(Vector2.One, healthLayout.RectTransform), string.Empty, textAlignment: Alignment.Center, font: GUIStyle.SubHeadingFont) new GUITextBlock(new RectTransform(Vector2.One, healthLayout.RectTransform), string.Empty, textAlignment: Alignment.Center, font: GUIStyle.SubHeadingFont)
{ {
TextGetter = () => $"{(int)(info.Character?.HealthPercentage ?? 100f)}%", TextGetter = () => TextManager.GetWithVariable("percentageformat", "[value]", $"{(int)(info.Character?.HealthPercentage ?? 100f)}"),
TextColor = GUIStyle.Green TextColor = GUIStyle.Green
}; };
@@ -850,7 +850,7 @@ namespace Barotrauma
GUILayoutGroup middleLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.66f), walletLayout.RectTransform)); GUILayoutGroup middleLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.66f), walletLayout.RectTransform));
GUILayoutGroup salaryTextLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), middleLayout.RectTransform), isHorizontal: true); GUILayoutGroup salaryTextLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), middleLayout.RectTransform), isHorizontal: true);
GUITextBlock salaryTitle = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), salaryTextLayout.RectTransform), TextManager.Get("crewwallet.salary"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.BottomLeft); GUITextBlock salaryTitle = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), salaryTextLayout.RectTransform), TextManager.Get("crewwallet.salary"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.BottomLeft);
GUITextBlock rewardBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), salaryTextLayout.RectTransform), $"{Mission.GetRewardShare(targetWallet.RewardDistribution, salaryCrew, Option<int>.None()).Percentage}%", textAlignment: Alignment.BottomRight); GUITextBlock rewardBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), salaryTextLayout.RectTransform), TextManager.GetWithVariable("percentageformat", "[value]", GetSharePercentage()), textAlignment: Alignment.BottomRight);
GUILayoutGroup sliderLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), middleLayout.RectTransform), isHorizontal: true, childAnchor: Anchor.Center); GUILayoutGroup sliderLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), middleLayout.RectTransform), isHorizontal: true, childAnchor: Anchor.Center);
GUIScrollBar salarySlider = new GUIScrollBar(new RectTransform(new Vector2(0.9f, 1f), sliderLayout.RectTransform), style: "GUISlider", barSize: 0.03f) GUIScrollBar salarySlider = new GUIScrollBar(new RectTransform(new Vector2(0.9f, 1f), sliderLayout.RectTransform), style: "GUISlider", barSize: 0.03f)
{ {
@@ -860,7 +860,7 @@ namespace Barotrauma
BarSize = 0.1f, BarSize = 0.1f,
OnMoved = (bar, scroll) => OnMoved = (bar, scroll) =>
{ {
rewardBlock.Text = $"{Mission.GetRewardShare((int)(scroll * 100f), salaryCrew, Option<int>.None()).Percentage}%"; rewardBlock.Text = TextManager.GetWithVariable("percentageformat", "[value]", GetSharePercentage());
return true; return true;
}, },
OnReleased = (bar, scroll) => OnReleased = (bar, scroll) =>
@@ -1090,10 +1090,7 @@ namespace Barotrauma
GameMain.Client?.ClientPeer?.Send(msg, DeliveryMethod.Reliable); GameMain.Client?.ClientPeer?.Send(msg, DeliveryMethod.Reliable);
} }
static int GetRewardDistributionPercentage(int distribution, ImmutableArray<Character> crew) string GetSharePercentage() => Mission.GetRewardShare(targetWallet.RewardDistribution, salaryCrew, Option<int>.None()).Percentage.ToString();
{
return Mission.GetRewardShare(distribution, crew, Option<int>.None()).Percentage;
}
} }
private GUIComponent CreateClientInfoFrame(GUIFrame frame, Client client, Sprite permissionIcon = null) private GUIComponent CreateClientInfoFrame(GUIFrame frame, Client client, Sprite permissionIcon = null)
@@ -184,7 +184,7 @@ namespace Barotrauma
} }
// Exchange money // Exchange money
Location.StoreCurrentBalance -= itemValue; Location.StoreCurrentBalance -= itemValue;
campaign.Wallet.TryDeduct(itemValue); campaign.Bank.Give(itemValue);
GameAnalyticsManager.AddMoneyGainedEvent(itemValue, GameAnalyticsManager.MoneySource.Store, item.ItemPrefab.Identifier.Value); GameAnalyticsManager.AddMoneyGainedEvent(itemValue, GameAnalyticsManager.MoneySource.Store, item.ItemPrefab.Identifier.Value);
// Remove from the sell crate // Remove from the sell crate
@@ -125,6 +125,7 @@ namespace Barotrauma
InitUI(); InitUI();
//backwards compatibility for saves made prior to the addition of personal wallets
int oldMoney = element.GetAttributeInt("money", 0); int oldMoney = element.GetAttributeInt("money", 0);
if (oldMoney > 0) if (oldMoney > 0)
{ {
@@ -315,9 +315,8 @@ namespace Barotrauma
int reward = displayedMission.GetReward(Submarine.MainSub); int reward = displayedMission.GetReward(Submarine.MainSub);
if (selectedMissions.Contains(displayedMission) && displayedMission.Completed && reward > 0) if (selectedMissions.Contains(displayedMission) && displayedMission.Completed && reward > 0)
{ {
LocalizedString rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", reward));
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), RichString.Rich(displayedMission.GetMissionRewardText(Submarine.MainSub))); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), RichString.Rich(displayedMission.GetMissionRewardText(Submarine.MainSub)));
if (Character.Controlled is { } controlled) if (GameMain.IsMultiplayer && Character.Controlled is { } controlled)
{ {
var (share, percentage) = Mission.GetRewardShare(controlled.Wallet.RewardDistribution, Mission.GetSalaryEligibleCrew(), Option<int>.Some(reward)); var (share, percentage) = Mission.GetRewardShare(controlled.Wallet.RewardDistribution, Mission.GetSalaryEligibleCrew(), Option<int>.Some(reward));
if (share > 0) if (share > 0)
@@ -677,7 +677,7 @@ namespace Barotrauma
if (item.ParentInventory == null) { continue; } if (item.ParentInventory == null) { continue; }
disabledItemLightCount += item.GetComponents<Items.Components.LightComponent>().Count(); disabledItemLightCount += item.GetComponents<Items.Components.LightComponent>().Count();
} }
return GameMain.LightManager.Lights.Count(l => l.CastShadows) - disabledItemLightCount; return GameMain.LightManager.Lights.Count(l => l.CastShadows && !l.IsBackground) - disabledItemLightCount;
} }
public void ClientReadPosition(IReadMessage msg, float sendingTime) public void ClientReadPosition(IReadMessage msg, float sendingTime)
@@ -666,8 +666,11 @@ namespace Barotrauma.Networking
if (ChildServerRelay.Process?.HasExited ?? true) if (ChildServerRelay.Process?.HasExited ?? true)
{ {
Disconnect(); Disconnect();
var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), ChildServerRelay.CrashMessage); if (!GUIMessageBox.MessageBoxes.Any(mb => (mb as GUIMessageBox).Text.Text == ChildServerRelay.CrashMessage))
msgBox.Buttons[0].OnClicked += ReturnToPreviousMenu; {
var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), ChildServerRelay.CrashMessage);
msgBox.Buttons[0].OnClicked += ReturnToPreviousMenu;
}
} }
} }
} }
@@ -243,9 +243,8 @@ namespace Barotrauma.CharacterEditor
character.AnimController.ForceSelectAnimationType = AnimationType.NotDefined; character.AnimController.ForceSelectAnimationType = AnimationType.NotDefined;
} }
public override void Deselect() protected override void DeselectEditorSpecific()
{ {
base.Deselect();
SoundPlayer.OverrideMusicType = Identifier.Empty; SoundPlayer.OverrideMusicType = Identifier.Empty;
GameMain.SoundManager.SetCategoryGainMultiplier("waterambience", GameSettings.CurrentConfig.Audio.SoundVolume, 0); GameMain.SoundManager.SetCategoryGainMultiplier("waterambience", GameSettings.CurrentConfig.Audio.SoundVolume, 0);
GUI.ForceMouseOn(null); GUI.ForceMouseOn(null);
@@ -7,6 +7,18 @@ namespace Barotrauma
public static Color BackgroundColor = GameSettings.CurrentConfig.SubEditorBackground; public static Color BackgroundColor = GameSettings.CurrentConfig.SubEditorBackground;
public override bool IsEditor => true; public override bool IsEditor => true;
public override sealed void Deselect()
{
DeselectEditorSpecific();
//reset cheats the player might have used in the editor
GameMain.LightManager.LightingEnabled = true;
GameMain.LightManager.LosEnabled = true;
Hull.EditFire = false;
Hull.EditWater = false;
}
protected virtual void DeselectEditorSpecific() { }
public void CreateBackgroundColorPicker() public void CreateBackgroundColorPicker()
{ {
var msgBox = new GUIMessageBox(TextManager.Get("CharacterEditor.EditBackgroundColor"), "", new[] { TextManager.Get("Reset"), TextManager.Get("OK")}, new Vector2(0.2f, 0.175f), minSize: new Point(300, 175)); var msgBox = new GUIMessageBox(TextManager.Get("CharacterEditor.EditBackgroundColor"), "", new[] { TextManager.Get("Reset"), TextManager.Get("OK")}, new Vector2(0.2f, 0.175f), minSize: new Point(300, 175));
@@ -519,11 +519,6 @@ namespace Barotrauma
base.Select(); base.Select();
} }
public override void Deselect()
{
base.Deselect();
}
public override void AddToGUIUpdateList() public override void AddToGUIUpdateList()
{ {
GuiFrame.AddToGUIUpdateList(); GuiFrame.AddToGUIUpdateList();
@@ -289,9 +289,8 @@ namespace Barotrauma
UpdateLevelObjectsList(); UpdateLevelObjectsList();
} }
public override void Deselect() protected override void DeselectEditorSpecific()
{ {
base.Deselect();
pointerLightSource?.Remove(); pointerLightSource?.Remove();
pointerLightSource = null; pointerLightSource = null;
} }
@@ -153,9 +153,8 @@ namespace Barotrauma
RefreshPrefabList(); RefreshPrefabList();
} }
public override void Deselect() protected override void DeselectEditorSpecific()
{ {
base.Deselect();
GameMain.ParticleManager.Camera = GameMain.GameScreen.Cam; GameMain.ParticleManager.Camera = GameMain.GameScreen.Cam;
filterBox.Text = ""; filterBox.Text = "";
} }
@@ -850,9 +850,8 @@ namespace Barotrauma
spriteList.Select(0, autoScroll: false); spriteList.Select(0, autoScroll: false);
} }
public override void Deselect() protected override void DeselectEditorSpecific()
{ {
base.Deselect();
loadedSprites.ForEach(s => s.Remove()); loadedSprites.ForEach(s => s.Remove());
loadedSprites.Clear(); loadedSprites.Clear();
ResetWidgets(); ResetWidgets();
@@ -22,7 +22,7 @@ namespace Barotrauma
public const int MaxStructures = 2000; public const int MaxStructures = 2000;
public const int MaxWalls = 500; public const int MaxWalls = 500;
public const int MaxItems = 5000; public const int MaxItems = 5000;
public const int MaxLights = 300; public const int MaxLights = 600;
public const int MaxShadowCastingLights = 60; public const int MaxShadowCastingLights = 60;
private static Submarine MainSub private static Submarine MainSub
@@ -852,7 +852,7 @@ namespace Barotrauma
lightCount += item.GetComponents<LightComponent>().Count(); lightCount += item.GetComponents<LightComponent>().Count();
} }
lightCountText.TextColor = lightCount > MaxLights ? GUIStyle.Red : Color.Lerp(GUIStyle.Green, GUIStyle.Orange, lightCount / (float)MaxLights); lightCountText.TextColor = lightCount > MaxLights ? GUIStyle.Red : Color.Lerp(GUIStyle.Green, GUIStyle.Orange, lightCount / (float)MaxLights);
return lightCount.ToString(); return lightCount.ToString() + "/" + MaxLights;
}; };
var shadowCastingLightCountLabel = new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.0f), paddedEntityCountPanel.RectTransform), TextManager.Get("SubEditorShadowCastingLights"), var shadowCastingLightCountLabel = new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.0f), paddedEntityCountPanel.RectTransform), TextManager.Get("SubEditorShadowCastingLights"),
textAlignment: Alignment.CenterLeft, font: GUIStyle.SmallFont, wrap: true); textAlignment: Alignment.CenterLeft, font: GUIStyle.SmallFont, wrap: true);
@@ -863,10 +863,10 @@ namespace Barotrauma
foreach (Item item in Item.ItemList) foreach (Item item in Item.ItemList)
{ {
if (item.ParentInventory != null) { continue; } if (item.ParentInventory != null) { continue; }
lightCount += item.GetComponents<LightComponent>().Count(l => l.CastShadows); lightCount += item.GetComponents<LightComponent>().Count(l => l.CastShadows && !l.DrawBehindSubs);
} }
shadowCastingLightCountText.TextColor = lightCount > MaxShadowCastingLights ? GUIStyle.Red : Color.Lerp(GUIStyle.Green, GUIStyle.Orange, lightCount / (float)MaxShadowCastingLights); shadowCastingLightCountText.TextColor = lightCount > MaxShadowCastingLights ? GUIStyle.Red : Color.Lerp(GUIStyle.Green, GUIStyle.Orange, lightCount / (float)MaxShadowCastingLights);
return lightCount.ToString(); return lightCount.ToString() + "/" + MaxShadowCastingLights;
}; };
entityCountPanel.RectTransform.NonScaledSize = entityCountPanel.RectTransform.NonScaledSize =
new Point( new Point(
@@ -1508,10 +1508,8 @@ namespace Barotrauma
yield return CoroutineStatus.Success; yield return CoroutineStatus.Success;
} }
public override void Deselect() protected override void DeselectEditorSpecific()
{ {
base.Deselect();
CloseItem(); CloseItem();
autoSaveLabel?.Parent?.RemoveChild(autoSaveLabel); autoSaveLabel?.Parent?.RemoveChild(autoSaveLabel);
@@ -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.1.0</Version> <Version>0.17.2.0</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright> <Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName> <AssemblyName>Barotrauma</AssemblyName>
+1 -1
View File
@@ -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.1.0</Version> <Version>0.17.2.0</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright> <Copyright>Copyright © FakeFish 2018-2020</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.1.0</Version> <Version>0.17.2.0</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright> <Copyright>Copyright © FakeFish 2018-2020</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.1.0</Version> <Version>0.17.2.0</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright> <Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName> <AssemblyName>DedicatedServer</AssemblyName>
+1 -1
View File
@@ -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.1.0</Version> <Version>0.17.2.0</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright> <Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName> <AssemblyName>DedicatedServer</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.1.0</Version> <Version>0.17.2.0</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright> <Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName> <AssemblyName>DedicatedServer</AssemblyName>
@@ -162,7 +162,9 @@ namespace Barotrauma
CloseEnough = reach, CloseEnough = reach,
DialogueIdentifier = Leak.FlowTargetHull != null ? "dialogcannotreachleak".ToIdentifier() : Identifier.Empty, DialogueIdentifier = Leak.FlowTargetHull != null ? "dialogcannotreachleak".ToIdentifier() : Identifier.Empty,
TargetName = Leak.FlowTargetHull?.DisplayName, TargetName = Leak.FlowTargetHull?.DisplayName,
requiredCondition = () => Leak.Submarine == character.Submarine, requiredCondition = () =>
Leak.Submarine == character.Submarine &&
(Leak.FlowTargetHull != null && character.CurrentHull == Leak.FlowTargetHull || character.CanSeeTarget(Leak)),
// The Go To objective can be abandoned if the leak is fixed (in which case we don't want to use the dialogue) // The Go To objective can be abandoned if the leak is fixed (in which case we don't want to use the dialogue)
SpeakCannotReachCondition = () => !CheckObjectiveSpecific() SpeakCannotReachCondition = () => !CheckObjectiveSpecific()
}, },
@@ -21,13 +21,25 @@ namespace Barotrauma
public CharacterInfoPrefab(ContentXElement headsElement, XElement varsElement, XElement menuCategoryElement, XElement pronounsElement) public CharacterInfoPrefab(ContentXElement headsElement, XElement varsElement, XElement menuCategoryElement, XElement pronounsElement)
{ {
Heads = headsElement.Elements().Select(e => new CharacterInfo.HeadPreset(this, e)).ToImmutableArray(); Heads = headsElement.Elements().Select(e => new CharacterInfo.HeadPreset(this, e)).ToImmutableArray();
VarTags = varsElement.Elements() if (varsElement != null)
.Select(e => {
(e.GetAttributeIdentifier("var", ""), VarTags = varsElement.Elements()
e.GetAttributeIdentifierArray("tags", Array.Empty<Identifier>()).ToImmutableHashSet())) .Select(e =>
.ToImmutableDictionary(); (e.GetAttributeIdentifier("var", ""),
MenuCategoryVar = menuCategoryElement.GetAttributeIdentifier("var", Identifier.Empty); e.GetAttributeIdentifierArray("tags", Array.Empty<Identifier>()).ToImmutableHashSet()))
Pronouns = pronounsElement.GetAttributeIdentifier("vars", Identifier.Empty); .ToImmutableDictionary();
}
else
{
VarTags = new[]
{
("GENDER".ToIdentifier(),
new[] { "female".ToIdentifier(), "male".ToIdentifier() }.ToImmutableHashSet())
}.ToImmutableDictionary();
}
MenuCategoryVar = menuCategoryElement?.GetAttributeIdentifier("var", Identifier.Empty) ?? "GENDER".ToIdentifier();
Pronouns = pronounsElement?.GetAttributeIdentifier("vars", Identifier.Empty) ?? "GENDER".ToIdentifier();
} }
public string ReplaceVars(string str, CharacterInfo.HeadPreset headPreset) public string ReplaceVars(string str, CharacterInfo.HeadPreset headPreset)
{ {
@@ -135,7 +147,13 @@ namespace Barotrauma
public string Tags public string Tags
{ {
get { return string.Join(",", TagSet); } get { return string.Join(",", TagSet); }
private set { TagSet = value.Split(",").Select(s => s.ToIdentifier()).ToImmutableHashSet(); } private set
{
TagSet = value.Split(",")
.Select(s => s.ToIdentifier())
.Where(id => !id.IsEmpty)
.ToImmutableHashSet();
}
} }
[Serialize("0,0", IsPropertySaveable.No)] [Serialize("0,0", IsPropertySaveable.No)]
@@ -149,6 +167,20 @@ namespace Barotrauma
{ {
characterInfoPrefab = charInfoPrefab; characterInfoPrefab = charInfoPrefab;
SerializableProperties = SerializableProperty.DeserializeProperties(this, element); SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
DetermineTagsFromLegacyFormat(element);
}
private void DetermineTagsFromLegacyFormat(XElement element)
{
void addTag(string tag)
=> TagSet = TagSet.Add(tag.ToIdentifier());
string headId = element.GetAttributeString("id", "");
string gender = element.GetAttributeString("gender", "");
string race = element.GetAttributeString("race", "");
if (!headId.IsNullOrEmpty()) { addTag($"head{headId}"); }
if (!gender.IsNullOrEmpty()) { addTag(gender); }
if (!race.IsNullOrEmpty()) { addTag(race); }
} }
} }
@@ -438,12 +470,37 @@ namespace Barotrauma
public readonly ImmutableArray<(Color Color, float Commonness)> FacialHairColors; public readonly ImmutableArray<(Color Color, float Commonness)> FacialHairColors;
public readonly ImmutableArray<(Color Color, float Commonness)> SkinColors; public readonly ImmutableArray<(Color Color, float Commonness)> SkinColors;
private void GetName(ContentPath namesFile, Rand.RandSync randSync, out string name) private void GetName(Rand.RandSync randSync, out string name)
{ {
XDocument doc = XMLExtensions.TryLoadXml(namesFile); var nameElement = CharacterConfigElement.GetChildElement("names") ?? CharacterConfigElement.GetChildElement("name");
name = doc.Root.GetAttributeString("format", ""); ContentPath namesXmlFile = nameElement?.GetAttributeContentPath("path") ?? ContentPath.Empty;
XElement namesXml = null;
if (!namesXmlFile.IsNullOrEmpty()) //names.xml is defined
{
XDocument doc = XMLExtensions.TryLoadXml(namesXmlFile);
namesXml = doc.Root;
}
else //the legacy firstnames.txt/lastnames.txt shit is defined
{
namesXml = new XElement("names", new XAttribute("format", "[firstname] [lastname]"));
var firstNamesPath = ReplaceVars(nameElement.GetAttributeContentPath("firstname")?.Value ?? "");
var lastNamesPath = ReplaceVars(nameElement.GetAttributeContentPath("lastname")?.Value ?? "");
if (File.Exists(firstNamesPath) && File.Exists(lastNamesPath))
{
var firstNames = File.ReadAllLines(firstNamesPath);
var lastNames = File.ReadAllLines(lastNamesPath);
namesXml.Add(firstNames.Select(n => new XElement("firstname", new XAttribute("value", n))));
namesXml.Add(lastNames.Select(n => new XElement("lastname", new XAttribute("value", n))));
}
else //the files don't exist, just fall back to the vanilla names
{
XDocument doc = XMLExtensions.TryLoadXml("Content/Characters/Human/names.xml");
namesXml = doc.Root;
}
}
name = namesXml.GetAttributeString("format", "");
Dictionary<Identifier, List<string>> entries = new Dictionary<Identifier, List<string>>(); Dictionary<Identifier, List<string>> entries = new Dictionary<Identifier, List<string>>();
foreach (var subElement in doc.Root.Elements()) foreach (var subElement in namesXml.Elements())
{ {
Identifier elemName = subElement.NameAsIdentifier(); Identifier elemName = subElement.NameAsIdentifier();
if (!entries.ContainsKey(elemName)) if (!entries.ContainsKey(elemName))
@@ -477,8 +534,21 @@ namespace Barotrauma
// talent-relevant values // talent-relevant values
public int MissionsCompletedSinceDeath = 0; public int MissionsCompletedSinceDeath = 0;
private static bool ElementHasSpecifierTags(XElement element)
=> element.GetAttributeBool("specifiertags",
element.GetAttributeBool("genders",
element.GetAttributeBool("races", false)));
// Used for creating the data // Used for creating the data
public CharacterInfo(Identifier speciesName, string name = "", string originalName = "", Either<Job, JobPrefab> jobOrJobPrefab = null, string ragdollFileName = null, int variant = 0, Rand.RandSync randSync = Rand.RandSync.Unsynced, Identifier npcIdentifier = default) public CharacterInfo(
Identifier speciesName,
string name = "",
string originalName = "",
Either<Job, JobPrefab> jobOrJobPrefab = null,
string ragdollFileName = null,
int variant = 0,
Rand.RandSync randSync = Rand.RandSync.Unsynced,
Identifier npcIdentifier = default)
{ {
JobPrefab jobPrefab = null; JobPrefab jobPrefab = null;
Job job = null; Job job = null;
@@ -494,7 +564,7 @@ namespace Barotrauma
CharacterConfigElement = CharacterPrefab.FindBySpeciesName(SpeciesName)?.ConfigElement; CharacterConfigElement = CharacterPrefab.FindBySpeciesName(SpeciesName)?.ConfigElement;
if (CharacterConfigElement == null) { return; } if (CharacterConfigElement == null) { return; }
// TODO: support for variants // TODO: support for variants
HasSpecifierTags = CharacterConfigElement.GetAttributeBool("specifiertags", false); HasSpecifierTags = ElementHasSpecifierTags(CharacterConfigElement);
if (HasSpecifierTags) if (HasSpecifierTags)
{ {
HairColors = CharacterConfigElement.GetAttributeTupleArray("haircolors", new (Color, float)[] { (Color.WhiteSmoke, 100f) }).ToImmutableArray(); HairColors = CharacterConfigElement.GetAttributeTupleArray("haircolors", new (Color, float)[] { (Color.WhiteSmoke, 100f) }).ToImmutableArray();
@@ -537,12 +607,7 @@ namespace Barotrauma
public string GetRandomName(Rand.RandSync randSync) public string GetRandomName(Rand.RandSync randSync)
{ {
string name = ""; GetName(randSync, out string name);
var nameElement = CharacterConfigElement.GetChildElement("names");
if (nameElement != null)
{
GetName(nameElement.GetAttributeContentPath("path") ?? ContentPath.Empty, randSync, out name);
}
return name; return name;
} }
@@ -623,7 +688,7 @@ namespace Barotrauma
if (element == null) { return; } if (element == null) { return; }
// TODO: support for variants // TODO: support for variants
CharacterConfigElement = element; CharacterConfigElement = element;
HasSpecifierTags = CharacterConfigElement.GetAttributeBool("specifiertags", false); HasSpecifierTags = ElementHasSpecifierTags(CharacterConfigElement);
if (HasSpecifierTags) if (HasSpecifierTags)
{ {
RecreateHead( RecreateHead(
@@ -647,7 +712,7 @@ namespace Barotrauma
var nameElement = CharacterConfigElement.GetChildElement("names"); var nameElement = CharacterConfigElement.GetChildElement("names");
if (nameElement != null) if (nameElement != null)
{ {
GetName(nameElement.GetAttributeContentPath("path") ?? ContentPath.Empty, Rand.RandSync.ServerAndClient, out Name); GetName(Rand.RandSync.ServerAndClient, out Name);
} }
} }
} }
@@ -36,7 +36,7 @@ namespace Barotrauma
var menuCategoryElement = ConfigElement.GetChildElement("MenuCategory"); var menuCategoryElement = ConfigElement.GetChildElement("MenuCategory");
var pronounsElement = ConfigElement.GetChildElement("Pronouns"); var pronounsElement = ConfigElement.GetChildElement("Pronouns");
if (headsElement != null && varsElement != null && menuCategoryElement != null && pronounsElement != null) if (headsElement != null)
{ {
CharacterInfoPrefab = new CharacterInfoPrefab(headsElement, varsElement, menuCategoryElement, pronounsElement); CharacterInfoPrefab = new CharacterInfoPrefab(headsElement, varsElement, menuCategoryElement, pronounsElement);
} }
@@ -380,20 +380,24 @@ namespace Barotrauma
public string Tags public string Tags
{ {
get { return string.Join(',', TagSet); } get { return string.Join(',', TagSet); }
private set { TagSet = value.Split(',').ToIdentifiers().ToImmutableHashSet(); } private set
{
TagSet = value.Split(',')
.ToIdentifiers()
.Where(id => !id.IsEmpty)
.ToImmutableHashSet();
}
} }
public ImmutableHashSet<Identifier> TagSet { get; private set; } public ImmutableHashSet<Identifier> TagSet { get; private set; }
public SoundParams(ContentXElement element, CharacterParams character) : base(element, character) public SoundParams(ContentXElement element, CharacterParams character) : base(element, character)
{ {
HashSet<Identifier> tags = TagSet.ToHashSet();
Identifier genderFallback = element.GetAttributeIdentifier("gender", ""); Identifier genderFallback = element.GetAttributeIdentifier("gender", "");
if (genderFallback != Identifier.Empty && genderFallback != "None") if (genderFallback != Identifier.Empty && genderFallback != "None")
{ {
tags.Add(genderFallback); TagSet = TagSet.Add(genderFallback);
} }
TagSet = tags.ToImmutableHashSet();
} }
} }
@@ -446,7 +446,7 @@ namespace Barotrauma
#elif CLIENT #elif CLIENT
return characters; return characters;
#endif #endif
static bool IsAlive(Character c) { return c.Info != null && !c.IsDead; } static bool IsAlive(Character c) { return c?.Info != null && !c.IsDead; }
} }
@@ -58,7 +58,7 @@ namespace Barotrauma
IsEquipped = new bool[capacity]; IsEquipped = new bool[capacity];
SlotTypes = new InvSlotType[capacity]; SlotTypes = new InvSlotType[capacity];
AccessibleWhenAlive = element.GetAttributeBool("accessiblewhenalive", false); AccessibleWhenAlive = element.GetAttributeBool("accessiblewhenalive", character.Info != null);
AccessibleByOwner = element.GetAttributeBool("accessiblebyowner", AccessibleWhenAlive); AccessibleByOwner = element.GetAttributeBool("accessiblebyowner", AccessibleWhenAlive);
string[] slotTypeNames = ParseSlotTypes(element); string[] slotTypeNames = ParseSlotTypes(element);
@@ -370,7 +370,7 @@ namespace Barotrauma.Items.Components
public Item GetFocusTarget() public Item GetFocusTarget()
{ {
var positionOut = item.Connections.Find(c => c.Name == "position_out"); var positionOut = item.Connections?.Find(c => c.Name == "position_out");
if (positionOut == null) { return null; } if (positionOut == null) { return null; }
item.SendSignal(new Signal(MathHelper.ToDegrees(targetRotation).ToString("G", CultureInfo.InvariantCulture), sender: user), positionOut); item.SendSignal(new Signal(MathHelper.ToDegrees(targetRotation).ToString("G", CultureInfo.InvariantCulture), sender: user), positionOut);
@@ -57,7 +57,7 @@ namespace Barotrauma.Items.Components
} }
[Editable, Serialize(true, IsPropertySaveable.Yes, description: "Should structures cast shadows when light from this light source hits them. " + [Editable, Serialize(true, IsPropertySaveable.Yes, description: "Should structures cast shadows when light from this light source hits them. " +
"Disabling shadows increases the performance of the game, and is recommended for lights with a short range.", alwaysUseInstanceValues: true)] "Disabling shadows increases the performance of the game, and is recommended for lights with a short range. Lights that are set to be drawn behind subs don't cast shadows, regardless of this setting.", alwaysUseInstanceValues: true)]
public bool CastShadows public bool CastShadows
{ {
get { return castShadows; } get { return castShadows; }
@@ -407,8 +407,6 @@ namespace Barotrauma
Loaded = this; Loaded = this;
Generating = true; Generating = true;
Rand.Tracker.Reset();
Rand.Tracker.Active = true;
EqualityCheckValues.Clear(); EqualityCheckValues.Clear();
EntitiesBeforeGenerate = GetEntities().ToList(); EntitiesBeforeGenerate = GetEntities().ToList();
EntityCountBeforeGenerate = EntitiesBeforeGenerate.Count(); EntityCountBeforeGenerate = EntitiesBeforeGenerate.Count();
@@ -1305,8 +1303,6 @@ namespace Barotrauma
//assign an ID to make entity events work //assign an ID to make entity events work
//ID = FindFreeID(); //ID = FindFreeID();
Generating = false; Generating = false;
Rand.Tracker.Active = false;
File.WriteAllLines(GameMain.NetworkMember is { IsServer: true } ? "serverrng.txt" : "clientrng.txt", Rand.Tracker.LogMsgs);
} }
private List<Point> GeneratePathNodes(Point startPosition, Point endPosition, Rectangle pathBorders, Tunnel parentTunnel, float variance) private List<Point> GeneratePathNodes(Point startPosition, Point endPosition, Rectangle pathBorders, Tunnel parentTunnel, float variance)
@@ -2443,7 +2439,6 @@ namespace Barotrauma
fixedResources.Add((itemPrefab, fixedQuantityResourceInfo)); fixedResources.Add((itemPrefab, fixedQuantityResourceInfo));
} }
} }
levelResources.Sort((x, y) => x.commonness.CompareTo(y.commonness));
DebugConsole.Log("Generating level resources..."); DebugConsole.Log("Generating level resources...");
var allValidLocations = GetAllValidClusterLocations(); var allValidLocations = GetAllValidClusterLocations();
@@ -2473,29 +2468,33 @@ namespace Barotrauma
//place some of the least common resources in the abyss //place some of the least common resources in the abyss
AbyssResources.Clear(); AbyssResources.Clear();
for (int j = 0; j < levelResources.Count && j < 5; j++)
{
for (int i = 0; i < 10; i++)
{
var (itemPrefab, commonness) = levelResources[j];
var location = allValidLocations.GetRandom(l =>
{
if (l.Cell == null || l.Edge == null) { return false; }
if (l.EdgeCenter.Y > AbyssArea.Bottom) { return false; }
l.InitializeResources();
return l.Resources.Count <= GetMaxResourcesOnEdge(itemPrefab, l, out _);
}, randSync: Rand.RandSync.ServerAndClient);
if (location.Cell == null || location.Edge == null) { break; } int abyssClusterCount = (int)MathHelper.Lerp(GenerationParams.AbyssResourceClustersMin, GenerationParams.AbyssResourceClustersMax, Difficulty / 100.0f);
int clusterSize = Rand.Range(GenerationParams.ResourceClusterSizeRange.X, GenerationParams.ResourceClusterSizeRange.Y + 1, Rand.RandSync.ServerAndClient);
PlaceResources(itemPrefab, clusterSize, location, out var abyssResources); for (int i = 0; i < abyssClusterCount; i++)
var abyssClusterLocation = new ClusterLocation(location.Cell, location.Edge, initializeResourceList: true); {
abyssClusterLocation.Resources.AddRange(abyssResources); //use inverse commonness to select the abyss resources (the rarest ones are the most common in the abyss)
AbyssResources.Add(abyssClusterLocation); var selectedPrefab = ToolBox.SelectWeightedRandom(
var locationIndex = allValidLocations.FindIndex(l => l.Equals(location)); levelResources.Select(it => it.itemPrefab).ToList(),
allValidLocations.RemoveAt(locationIndex); levelResources.Select(it => it.commonness <= 0.0f ? 0.0f : 1.0f / it.commonness).ToList(),
} Rand.RandSync.ServerAndClient);
} var location = allValidLocations.GetRandom(l =>
{
if (l.Cell == null || l.Edge == null) { return false; }
if (l.EdgeCenter.Y > AbyssArea.Bottom) { return false; }
l.InitializeResources();
return l.Resources.Count <= GetMaxResourcesOnEdge(selectedPrefab, l, out _);
}, randSync: Rand.RandSync.ServerAndClient);
if (location.Cell == null || location.Edge == null) { break; }
int clusterSize = Rand.Range(GenerationParams.ResourceClusterSizeRange.X, GenerationParams.ResourceClusterSizeRange.Y + 1, Rand.RandSync.ServerAndClient);
PlaceResources(selectedPrefab, clusterSize, location, out var abyssResources);
var abyssClusterLocation = new ClusterLocation(location.Cell, location.Edge, initializeResourceList: true);
abyssClusterLocation.Resources.AddRange(abyssResources);
AbyssResources.Add(abyssClusterLocation);
var locationIndex = allValidLocations.FindIndex(l => l.Equals(location));
allValidLocations.RemoveAt(locationIndex);
}
PathPoints.Clear(); PathPoints.Clear();
nextPathPointId = 0; nextPathPointId = 0;
@@ -2603,7 +2602,14 @@ namespace Barotrauma
#if DEBUG #if DEBUG
DebugConsole.NewMessage("Level resources spawned: " + itemCount + "\n" + DebugConsole.NewMessage("Level resources spawned: " + itemCount + "\n" +
"Spawn points containing resources: " + PathPoints.Where(p => p.ClusterLocations.Any()).Count() + "/" + PathPoints.Count); " Spawn points containing resources: " + PathPoints.Where(p => p.ClusterLocations.Any()).Count() + "/" + PathPoints.Count + "\n" +
" Total value: "+ PathPoints.Sum(p => p.ClusterLocations.Sum(c => c.Resources.Sum(r => r.Prefab.DefaultPrice?.Price ?? 0)))+" mk");
if (AbyssResources.Count > 0)
{
DebugConsole.NewMessage("Abyss resources spawned: " + AbyssResources.Sum(a => a.Resources.Count) + "\n" +
" Total value: " + AbyssResources.Sum(c => c.Resources.Sum(r => r.Prefab.DefaultPrice?.Price ?? 0)) + " mk");
}
#endif #endif
DebugConsole.Log("Level resources generated"); DebugConsole.Log("Level resources generated");
@@ -387,6 +387,20 @@ namespace Barotrauma
set; set;
} }
[Serialize(3, IsPropertySaveable.Yes, description: "Minimum number of resource clusters in the abyss (the actual number is picked between min and max according to the level difficulty)"), Editable(MinValueInt = 0, MaxValueInt = 1000)]
public int AbyssResourceClustersMin
{
get;
set;
}
[Serialize(20, IsPropertySaveable.Yes, description: "Maximum number of resource clusters in the abyss (the actual number is picked between min and max according to the level difficulty)"), Editable(MinValueInt = 0, MaxValueInt = 1000)]
public int AbyssResourceClustersMax
{
get;
set;
}
[Serialize(-300000, IsPropertySaveable.Yes, description: "How far below the level the sea floor is placed."), Editable(MinValueFloat = Level.MaxEntityDepth, MaxValueFloat = 0.0f)] [Serialize(-300000, IsPropertySaveable.Yes, description: "How far below the level the sea floor is placed."), Editable(MinValueFloat = Level.MaxEntityDepth, MaxValueFloat = 0.0f)]
public int SeaFloorDepth public int SeaFloorDepth
{ {
@@ -11,38 +11,6 @@ namespace Barotrauma
{ {
public static class Rand public static class Rand
{ {
[Obsolete("TODO: remove")]
public static class Tracker
{
private readonly static List<string> logMsgs = new List<string>();
public static IReadOnlyList<string> LogMsgs => logMsgs;
public static bool Active = false;
public static void Reset()
{
logMsgs.Clear();
Active = false;
}
public static void RegisterCall(int stDepth=4)
{
if (!Active) { return; }
var st = new StackTrace(skipFrames: 2, fNeedFileInfo: true);
var frames = st.GetFrames();
string msg = string.Join("; ",
frames.Take(stDepth).Select(f =>
$"{Path.GetFileNameWithoutExtension(f.GetFileName())}:{f.GetFileLineNumber()}"));
logMsgs.Add(msg);
}
public static void Log(string msg)
{
if (!Active) { return; }
logMsgs.Add(msg);
}
}
public enum RandSync public enum RandSync
{ {
Unsynced, //not synced, used for unimportant details like minor particle properties Unsynced, //not synced, used for unimportant details like minor particle properties
@@ -81,8 +49,6 @@ namespace Barotrauma
public static int ThreadId = 0; public static int ThreadId = 0;
private static void CheckRandThreadSafety(RandSync sync) private static void CheckRandThreadSafety(RandSync sync)
{ {
if (sync == RandSync.ServerAndClient) { Tracker.RegisterCall(); }
if (ThreadId != 0 && sync == RandSync.Unsynced) if (ThreadId != 0 && sync == RandSync.Unsynced)
{ {
if (System.Threading.Thread.CurrentThread.ManagedThreadId != ThreadId) if (System.Threading.Thread.CurrentThread.ManagedThreadId != ThreadId)
+21
View File
@@ -1,3 +1,24 @@
---------------------------------------------------------------------------------------------------------
v0.17.2.0
---------------------------------------------------------------------------------------------------------
Changes:
- Adjusted abyss resource spawning: less resources per level, the number of resources is relative to the difficulty, the spawned resources aren't guaranteed to always be the 5 least common alien materials.
- Increased maximum number of lights from 300 to 600 (unstable only).
- Backwards compatibility with human mods made before modding refactor (unstable only).
Fixes:
- Fixed server crash in GetSalaryEligibleCrew (unstable only).
- Fixed crashing in Controller.GetFocusTarget (unstable only).
- Fixed "Tried to access crew wallets in singleplayer" error at the end of the round (unstable only).
- Fixed selling items taking money instead of giving it (unstable only).
- Fixed lights that are drawn behind subs counting as shadow-casting in the sub editor.
- Fixed server host creating 2 disconnect message boxes if the server crashes.
- Deactivate certain cheats when leaving an editor. Fixes ability to use certain cheat commands in an editor (which is now allowed without having to enable cheats) and then switch back to the game (unstable only).
AI:
- Fixed bots sometimes getting stuck to doors when they are trying to fix a hull behind it. Happened because the goto objective was completed before the bot could open the door.
--------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------
v0.17.1.0 v0.17.1.0
--------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------