Unstable 0.17.2.0
This commit is contained in:
@@ -842,7 +842,7 @@ namespace Barotrauma
|
||||
ContentXElement headElement = info.Ragdoll.MainElement.Elements().FirstOrDefault(e =>
|
||||
e.GetAttributeString("type", "").Equals("head", StringComparison.OrdinalIgnoreCase));
|
||||
ContentXElement headSpriteElement = headElement.GetChildElement("sprite");
|
||||
string spritePathWithTags = headSpriteElement.Attribute("texture").Value;
|
||||
ContentPath spritePathWithTags = headSpriteElement.GetAttributeContentPath("texture");
|
||||
|
||||
var characterConfigElement = info.CharacterConfigElement;
|
||||
|
||||
@@ -853,7 +853,7 @@ namespace Barotrauma
|
||||
itemsInRow = 0;
|
||||
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; }
|
||||
|
||||
|
||||
@@ -521,7 +521,7 @@ namespace Barotrauma
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
@@ -850,7 +850,7 @@ namespace Barotrauma
|
||||
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);
|
||||
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);
|
||||
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,
|
||||
OnMoved = (bar, scroll) =>
|
||||
{
|
||||
rewardBlock.Text = $"{Mission.GetRewardShare((int)(scroll * 100f), salaryCrew, Option<int>.None()).Percentage}%";
|
||||
rewardBlock.Text = TextManager.GetWithVariable("percentageformat", "[value]", GetSharePercentage());
|
||||
return true;
|
||||
},
|
||||
OnReleased = (bar, scroll) =>
|
||||
@@ -1090,10 +1090,7 @@ namespace Barotrauma
|
||||
GameMain.Client?.ClientPeer?.Send(msg, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
static int GetRewardDistributionPercentage(int distribution, ImmutableArray<Character> crew)
|
||||
{
|
||||
return Mission.GetRewardShare(distribution, crew, Option<int>.None()).Percentage;
|
||||
}
|
||||
string GetSharePercentage() => Mission.GetRewardShare(targetWallet.RewardDistribution, salaryCrew, Option<int>.None()).Percentage.ToString();
|
||||
}
|
||||
|
||||
private GUIComponent CreateClientInfoFrame(GUIFrame frame, Client client, Sprite permissionIcon = null)
|
||||
|
||||
@@ -184,7 +184,7 @@ namespace Barotrauma
|
||||
}
|
||||
// Exchange money
|
||||
Location.StoreCurrentBalance -= itemValue;
|
||||
campaign.Wallet.TryDeduct(itemValue);
|
||||
campaign.Bank.Give(itemValue);
|
||||
GameAnalyticsManager.AddMoneyGainedEvent(itemValue, GameAnalyticsManager.MoneySource.Store, item.ItemPrefab.Identifier.Value);
|
||||
|
||||
// Remove from the sell crate
|
||||
|
||||
@@ -125,6 +125,7 @@ namespace Barotrauma
|
||||
|
||||
InitUI();
|
||||
|
||||
//backwards compatibility for saves made prior to the addition of personal wallets
|
||||
int oldMoney = element.GetAttributeInt("money", 0);
|
||||
if (oldMoney > 0)
|
||||
{
|
||||
|
||||
@@ -315,9 +315,8 @@ namespace Barotrauma
|
||||
int reward = displayedMission.GetReward(Submarine.MainSub);
|
||||
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)));
|
||||
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));
|
||||
if (share > 0)
|
||||
|
||||
@@ -677,7 +677,7 @@ namespace Barotrauma
|
||||
if (item.ParentInventory == null) { continue; }
|
||||
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)
|
||||
|
||||
@@ -666,8 +666,11 @@ namespace Barotrauma.Networking
|
||||
if (ChildServerRelay.Process?.HasExited ?? true)
|
||||
{
|
||||
Disconnect();
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), ChildServerRelay.CrashMessage);
|
||||
msgBox.Buttons[0].OnClicked += ReturnToPreviousMenu;
|
||||
if (!GUIMessageBox.MessageBoxes.Any(mb => (mb as GUIMessageBox).Text.Text == ChildServerRelay.CrashMessage))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
public override void Deselect()
|
||||
protected override void DeselectEditorSpecific()
|
||||
{
|
||||
base.Deselect();
|
||||
SoundPlayer.OverrideMusicType = Identifier.Empty;
|
||||
GameMain.SoundManager.SetCategoryGainMultiplier("waterambience", GameSettings.CurrentConfig.Audio.SoundVolume, 0);
|
||||
GUI.ForceMouseOn(null);
|
||||
|
||||
@@ -7,6 +7,18 @@ namespace Barotrauma
|
||||
public static Color BackgroundColor = GameSettings.CurrentConfig.SubEditorBackground;
|
||||
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()
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
public override void Deselect()
|
||||
{
|
||||
base.Deselect();
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
GuiFrame.AddToGUIUpdateList();
|
||||
|
||||
@@ -289,9 +289,8 @@ namespace Barotrauma
|
||||
UpdateLevelObjectsList();
|
||||
}
|
||||
|
||||
public override void Deselect()
|
||||
protected override void DeselectEditorSpecific()
|
||||
{
|
||||
base.Deselect();
|
||||
pointerLightSource?.Remove();
|
||||
pointerLightSource = null;
|
||||
}
|
||||
|
||||
@@ -153,9 +153,8 @@ namespace Barotrauma
|
||||
RefreshPrefabList();
|
||||
}
|
||||
|
||||
public override void Deselect()
|
||||
protected override void DeselectEditorSpecific()
|
||||
{
|
||||
base.Deselect();
|
||||
GameMain.ParticleManager.Camera = GameMain.GameScreen.Cam;
|
||||
filterBox.Text = "";
|
||||
}
|
||||
|
||||
@@ -850,9 +850,8 @@ namespace Barotrauma
|
||||
spriteList.Select(0, autoScroll: false);
|
||||
}
|
||||
|
||||
public override void Deselect()
|
||||
protected override void DeselectEditorSpecific()
|
||||
{
|
||||
base.Deselect();
|
||||
loadedSprites.ForEach(s => s.Remove());
|
||||
loadedSprites.Clear();
|
||||
ResetWidgets();
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Barotrauma
|
||||
public const int MaxStructures = 2000;
|
||||
public const int MaxWalls = 500;
|
||||
public const int MaxItems = 5000;
|
||||
public const int MaxLights = 300;
|
||||
public const int MaxLights = 600;
|
||||
public const int MaxShadowCastingLights = 60;
|
||||
|
||||
private static Submarine MainSub
|
||||
@@ -852,7 +852,7 @@ namespace Barotrauma
|
||||
lightCount += item.GetComponents<LightComponent>().Count();
|
||||
}
|
||||
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"),
|
||||
textAlignment: Alignment.CenterLeft, font: GUIStyle.SmallFont, wrap: true);
|
||||
@@ -863,10 +863,10 @@ namespace Barotrauma
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
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);
|
||||
return lightCount.ToString();
|
||||
return lightCount.ToString() + "/" + MaxShadowCastingLights;
|
||||
};
|
||||
entityCountPanel.RectTransform.NonScaledSize =
|
||||
new Point(
|
||||
@@ -1508,10 +1508,8 @@ namespace Barotrauma
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
public override void Deselect()
|
||||
protected override void DeselectEditorSpecific()
|
||||
{
|
||||
base.Deselect();
|
||||
|
||||
CloseItem();
|
||||
|
||||
autoSaveLabel?.Parent?.RemoveChild(autoSaveLabel);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.17.1.0</Version>
|
||||
<Version>0.17.2.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.17.1.0</Version>
|
||||
<Version>0.17.2.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.17.1.0</Version>
|
||||
<Version>0.17.2.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.17.1.0</Version>
|
||||
<Version>0.17.2.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.17.1.0</Version>
|
||||
<Version>0.17.2.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.17.1.0</Version>
|
||||
<Version>0.17.2.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -162,7 +162,9 @@ namespace Barotrauma
|
||||
CloseEnough = reach,
|
||||
DialogueIdentifier = Leak.FlowTargetHull != null ? "dialogcannotreachleak".ToIdentifier() : Identifier.Empty,
|
||||
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)
|
||||
SpeakCannotReachCondition = () => !CheckObjectiveSpecific()
|
||||
},
|
||||
|
||||
@@ -21,13 +21,25 @@ namespace Barotrauma
|
||||
public CharacterInfoPrefab(ContentXElement headsElement, XElement varsElement, XElement menuCategoryElement, XElement pronounsElement)
|
||||
{
|
||||
Heads = headsElement.Elements().Select(e => new CharacterInfo.HeadPreset(this, e)).ToImmutableArray();
|
||||
VarTags = varsElement.Elements()
|
||||
.Select(e =>
|
||||
(e.GetAttributeIdentifier("var", ""),
|
||||
e.GetAttributeIdentifierArray("tags", Array.Empty<Identifier>()).ToImmutableHashSet()))
|
||||
.ToImmutableDictionary();
|
||||
MenuCategoryVar = menuCategoryElement.GetAttributeIdentifier("var", Identifier.Empty);
|
||||
Pronouns = pronounsElement.GetAttributeIdentifier("vars", Identifier.Empty);
|
||||
if (varsElement != null)
|
||||
{
|
||||
VarTags = varsElement.Elements()
|
||||
.Select(e =>
|
||||
(e.GetAttributeIdentifier("var", ""),
|
||||
e.GetAttributeIdentifierArray("tags", Array.Empty<Identifier>()).ToImmutableHashSet()))
|
||||
.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)
|
||||
{
|
||||
@@ -135,7 +147,13 @@ namespace Barotrauma
|
||||
public string Tags
|
||||
{
|
||||
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)]
|
||||
@@ -149,6 +167,20 @@ namespace Barotrauma
|
||||
{
|
||||
characterInfoPrefab = charInfoPrefab;
|
||||
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)> 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);
|
||||
name = doc.Root.GetAttributeString("format", "");
|
||||
var nameElement = CharacterConfigElement.GetChildElement("names") ?? CharacterConfigElement.GetChildElement("name");
|
||||
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>>();
|
||||
foreach (var subElement in doc.Root.Elements())
|
||||
foreach (var subElement in namesXml.Elements())
|
||||
{
|
||||
Identifier elemName = subElement.NameAsIdentifier();
|
||||
if (!entries.ContainsKey(elemName))
|
||||
@@ -477,8 +534,21 @@ namespace Barotrauma
|
||||
// talent-relevant values
|
||||
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
|
||||
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;
|
||||
Job job = null;
|
||||
@@ -494,7 +564,7 @@ namespace Barotrauma
|
||||
CharacterConfigElement = CharacterPrefab.FindBySpeciesName(SpeciesName)?.ConfigElement;
|
||||
if (CharacterConfigElement == null) { return; }
|
||||
// TODO: support for variants
|
||||
HasSpecifierTags = CharacterConfigElement.GetAttributeBool("specifiertags", false);
|
||||
HasSpecifierTags = ElementHasSpecifierTags(CharacterConfigElement);
|
||||
if (HasSpecifierTags)
|
||||
{
|
||||
HairColors = CharacterConfigElement.GetAttributeTupleArray("haircolors", new (Color, float)[] { (Color.WhiteSmoke, 100f) }).ToImmutableArray();
|
||||
@@ -537,12 +607,7 @@ namespace Barotrauma
|
||||
|
||||
public string GetRandomName(Rand.RandSync randSync)
|
||||
{
|
||||
string name = "";
|
||||
var nameElement = CharacterConfigElement.GetChildElement("names");
|
||||
if (nameElement != null)
|
||||
{
|
||||
GetName(nameElement.GetAttributeContentPath("path") ?? ContentPath.Empty, randSync, out name);
|
||||
}
|
||||
GetName(randSync, out string name);
|
||||
|
||||
return name;
|
||||
}
|
||||
@@ -623,7 +688,7 @@ namespace Barotrauma
|
||||
if (element == null) { return; }
|
||||
// TODO: support for variants
|
||||
CharacterConfigElement = element;
|
||||
HasSpecifierTags = CharacterConfigElement.GetAttributeBool("specifiertags", false);
|
||||
HasSpecifierTags = ElementHasSpecifierTags(CharacterConfigElement);
|
||||
if (HasSpecifierTags)
|
||||
{
|
||||
RecreateHead(
|
||||
@@ -647,7 +712,7 @@ namespace Barotrauma
|
||||
var nameElement = CharacterConfigElement.GetChildElement("names");
|
||||
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 pronounsElement = ConfigElement.GetChildElement("Pronouns");
|
||||
|
||||
if (headsElement != null && varsElement != null && menuCategoryElement != null && pronounsElement != null)
|
||||
if (headsElement != null)
|
||||
{
|
||||
CharacterInfoPrefab = new CharacterInfoPrefab(headsElement, varsElement, menuCategoryElement, pronounsElement);
|
||||
}
|
||||
|
||||
@@ -380,20 +380,24 @@ namespace Barotrauma
|
||||
public string Tags
|
||||
{
|
||||
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 SoundParams(ContentXElement element, CharacterParams character) : base(element, character)
|
||||
{
|
||||
HashSet<Identifier> tags = TagSet.ToHashSet();
|
||||
Identifier genderFallback = element.GetAttributeIdentifier("gender", "");
|
||||
if (genderFallback != Identifier.Empty && genderFallback != "None")
|
||||
{
|
||||
tags.Add(genderFallback);
|
||||
TagSet = TagSet.Add(genderFallback);
|
||||
}
|
||||
TagSet = tags.ToImmutableHashSet();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -446,7 +446,7 @@ namespace Barotrauma
|
||||
#elif CLIENT
|
||||
return characters;
|
||||
#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];
|
||||
SlotTypes = new InvSlotType[capacity];
|
||||
|
||||
AccessibleWhenAlive = element.GetAttributeBool("accessiblewhenalive", false);
|
||||
AccessibleWhenAlive = element.GetAttributeBool("accessiblewhenalive", character.Info != null);
|
||||
AccessibleByOwner = element.GetAttributeBool("accessiblebyowner", AccessibleWhenAlive);
|
||||
|
||||
string[] slotTypeNames = ParseSlotTypes(element);
|
||||
|
||||
@@ -370,7 +370,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
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; }
|
||||
|
||||
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. " +
|
||||
"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
|
||||
{
|
||||
get { return castShadows; }
|
||||
|
||||
@@ -407,8 +407,6 @@ namespace Barotrauma
|
||||
Loaded = this;
|
||||
Generating = true;
|
||||
|
||||
Rand.Tracker.Reset();
|
||||
Rand.Tracker.Active = true;
|
||||
EqualityCheckValues.Clear();
|
||||
EntitiesBeforeGenerate = GetEntities().ToList();
|
||||
EntityCountBeforeGenerate = EntitiesBeforeGenerate.Count();
|
||||
@@ -1305,8 +1303,6 @@ namespace Barotrauma
|
||||
//assign an ID to make entity events work
|
||||
//ID = FindFreeID();
|
||||
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)
|
||||
@@ -2443,7 +2439,6 @@ namespace Barotrauma
|
||||
fixedResources.Add((itemPrefab, fixedQuantityResourceInfo));
|
||||
}
|
||||
}
|
||||
levelResources.Sort((x, y) => x.commonness.CompareTo(y.commonness));
|
||||
|
||||
DebugConsole.Log("Generating level resources...");
|
||||
var allValidLocations = GetAllValidClusterLocations();
|
||||
@@ -2473,29 +2468,33 @@ namespace Barotrauma
|
||||
|
||||
//place some of the least common resources in the abyss
|
||||
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 clusterSize = Rand.Range(GenerationParams.ResourceClusterSizeRange.X, GenerationParams.ResourceClusterSizeRange.Y + 1, Rand.RandSync.ServerAndClient);
|
||||
PlaceResources(itemPrefab, 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);
|
||||
}
|
||||
}
|
||||
int abyssClusterCount = (int)MathHelper.Lerp(GenerationParams.AbyssResourceClustersMin, GenerationParams.AbyssResourceClustersMax, Difficulty / 100.0f);
|
||||
|
||||
for (int i = 0; i < abyssClusterCount; i++)
|
||||
{
|
||||
//use inverse commonness to select the abyss resources (the rarest ones are the most common in the abyss)
|
||||
var selectedPrefab = ToolBox.SelectWeightedRandom(
|
||||
levelResources.Select(it => it.itemPrefab).ToList(),
|
||||
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();
|
||||
nextPathPointId = 0;
|
||||
@@ -2603,7 +2602,14 @@ namespace Barotrauma
|
||||
|
||||
#if DEBUG
|
||||
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
|
||||
|
||||
DebugConsole.Log("Level resources generated");
|
||||
|
||||
@@ -387,6 +387,20 @@ namespace Barotrauma
|
||||
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)]
|
||||
public int SeaFloorDepth
|
||||
{
|
||||
|
||||
@@ -11,38 +11,6 @@ namespace Barotrauma
|
||||
{
|
||||
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
|
||||
{
|
||||
Unsynced, //not synced, used for unimportant details like minor particle properties
|
||||
@@ -81,8 +49,6 @@ namespace Barotrauma
|
||||
public static int ThreadId = 0;
|
||||
private static void CheckRandThreadSafety(RandSync sync)
|
||||
{
|
||||
if (sync == RandSync.ServerAndClient) { Tracker.RegisterCall(); }
|
||||
|
||||
if (ThreadId != 0 && sync == RandSync.Unsynced)
|
||||
{
|
||||
if (System.Threading.Thread.CurrentThread.ManagedThreadId != ThreadId)
|
||||
|
||||
@@ -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
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user